766 lines
17 KiB
C
766 lines
17 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
netboot.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the net boot file system used by the operating
|
|||
|
system loader.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Chuck Lenzmeier (chuckl) 09-Jan-1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "bootlib.h"
|
|||
|
#include "stdio.h"
|
|||
|
|
|||
|
#ifdef UINT16
|
|||
|
#undef UINT16
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef INT16
|
|||
|
#undef INT16
|
|||
|
#endif
|
|||
|
|
|||
|
#include <dhcp.h>
|
|||
|
#include <netfs.h>
|
|||
|
#include <pxe_cmn.h>
|
|||
|
|
|||
|
#include <pxe_api.h>
|
|||
|
|
|||
|
#include <udp_api.h>
|
|||
|
#include <tftp_api.h>
|
|||
|
#if defined(_IA64_)
|
|||
|
#include "bootia64.h"
|
|||
|
#else
|
|||
|
#include "bootx86.h"
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef BOOL
|
|||
|
typedef int BOOL;
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef FALSE
|
|||
|
#define FALSE 0
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef TRUE
|
|||
|
#define TRUE 1
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef BYTE
|
|||
|
typedef unsigned char BYTE;
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef LPBYTE
|
|||
|
typedef BYTE *LPBYTE;
|
|||
|
#endif
|
|||
|
|
|||
|
#define MAX_PATH 260
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Define global data.
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN BlBootingFromNet = FALSE;
|
|||
|
|
|||
|
BOOLEAN NetBootInitialized = FALSE;
|
|||
|
|
|||
|
PARC_OPEN_ROUTINE NetRealArcOpenRoutine;
|
|||
|
PARC_CLOSE_ROUTINE NetRealArcCloseRoutine;
|
|||
|
|
|||
|
BL_DEVICE_ENTRY_TABLE NetDeviceEntryTable;
|
|||
|
|
|||
|
BOOTFS_INFO NetBootFsInfo={L"net"};
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT_SECURITY)
|
|||
|
ULONG TftpSecurityHandle = 0;
|
|||
|
#endif // defined(REMOTE_BOOT_SECURITY)
|
|||
|
|
|||
|
BOOLEAN NetBootTftpUsedPassword2;
|
|||
|
|
|||
|
//
|
|||
|
// We cache the last file opened, in case we get a request to open it again.
|
|||
|
// We don't save a copy of the data, just a pointer to the data read by that
|
|||
|
// open. So if the original open is closed before the next open for the
|
|||
|
// same file comes in, we won't get a cache hit. But this system works for
|
|||
|
// reading compressed files, which is the situation we care about. In that
|
|||
|
// case a file is opened once and then re-opened twice more before the
|
|||
|
// original open is closed.
|
|||
|
//
|
|||
|
|
|||
|
ULONG CachedFileDeviceId = 0;
|
|||
|
UCHAR CachedFilePath[MAX_PATH];
|
|||
|
ULONG CachedFileSize = 0;
|
|||
|
PUCHAR CachedFileData = NULL;
|
|||
|
|
|||
|
extern ARC_STATUS
|
|||
|
GetParametersFromRom (
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
PBL_DEVICE_ENTRY_TABLE
|
|||
|
IsNetFileStructure (
|
|||
|
IN ULONG DeviceId,
|
|||
|
IN PVOID StructureContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine determines if the partition on the specified channel
|
|||
|
contains a net file system volume.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceId - Supplies the file table index for the device on which
|
|||
|
read operations are to be performed.
|
|||
|
|
|||
|
StructureContext - Supplies a pointer to a net file structure context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A pointer to the net entry table is returned if the partition is
|
|||
|
recognized as containing a net volume. Otherwise, NULL is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PNET_STRUCTURE_CONTEXT NetStructureContext;
|
|||
|
|
|||
|
DPRINT( TRACE, ("IsNetFileStructure\n") );
|
|||
|
|
|||
|
if ( !BlBootingFromNet || (DeviceId != NET_DEVICE_ID) ) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear the file system context block for the specified channel and
|
|||
|
// establish a pointer to the context structure that can be used by other
|
|||
|
// routines
|
|||
|
//
|
|||
|
|
|||
|
NetStructureContext = (PNET_STRUCTURE_CONTEXT)StructureContext;
|
|||
|
RtlZeroMemory(NetStructureContext, sizeof(NET_STRUCTURE_CONTEXT));
|
|||
|
|
|||
|
//
|
|||
|
// Return the address of the table.
|
|||
|
//
|
|||
|
|
|||
|
return &NetDeviceEntryTable;
|
|||
|
|
|||
|
} // IsNetFileStructure
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetInitialize (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the net boot filesystem.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
DPRINT( TRACE, ("NetInitialize\n") );
|
|||
|
//DbgBreakPoint( );
|
|||
|
|
|||
|
|
|||
|
if( NetBootInitialized ) {
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the file entry table. Note that we need to do
|
|||
|
// this even if we aren't booting from the net because we may
|
|||
|
// use the 'Net' I/O functions to lay on top of any files that
|
|||
|
// we download through the debugger port. So for that case,
|
|||
|
// we need access to all these functions here (see bd\file.c)
|
|||
|
//
|
|||
|
NetDeviceEntryTable.Close = NetClose;
|
|||
|
NetDeviceEntryTable.Mount = NetMount;
|
|||
|
NetDeviceEntryTable.Open = NetOpen;
|
|||
|
NetDeviceEntryTable.Read = NetRead;
|
|||
|
NetDeviceEntryTable.GetReadStatus = NetGetReadStatus;
|
|||
|
NetDeviceEntryTable.Seek = NetSeek;
|
|||
|
NetDeviceEntryTable.Write = NetWrite;
|
|||
|
NetDeviceEntryTable.GetFileInformation = NetGetFileInformation;
|
|||
|
NetDeviceEntryTable.SetFileInformation = NetSetFileInformation;
|
|||
|
NetDeviceEntryTable.Rename = NetRename;
|
|||
|
NetDeviceEntryTable.GetDirectoryEntry = NetGetDirectoryEntry;
|
|||
|
NetDeviceEntryTable.BootFsInfo = &NetBootFsInfo;
|
|||
|
|
|||
|
if( !BlBootingFromNet ) {
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NetBootInitialized = TRUE;
|
|||
|
|
|||
|
DPRINT( LOUD, ("NetInitialize: booting from net\n") );
|
|||
|
//DPRINT( LOUD, (" NetInitialize at %08x\n", NetInitialize) );
|
|||
|
//DPRINT( LOUD, (" NetOpen at %08x\n", NetOpen) );
|
|||
|
//DbgBreakPoint( );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Hook the ArcOpen and ArcClose routines.
|
|||
|
//
|
|||
|
|
|||
|
NetRealArcOpenRoutine = SYSTEM_BLOCK->FirmwareVector[OpenRoutine];
|
|||
|
SYSTEM_BLOCK->FirmwareVector[OpenRoutine] = NetArcOpen;
|
|||
|
|
|||
|
NetRealArcCloseRoutine = SYSTEM_BLOCK->FirmwareVector[CloseRoutine];
|
|||
|
SYSTEM_BLOCK->FirmwareVector[CloseRoutine] = NetArcClose;
|
|||
|
|
|||
|
//
|
|||
|
// Get boot parameters from the boot ROM.
|
|||
|
//
|
|||
|
|
|||
|
status = GetParametersFromRom( );
|
|||
|
|
|||
|
if ( status != ESUCCESS ) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NetTerminate (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine shuts down the net boot filesystem.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
#if defined(_X86_)
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT_SECURITY)
|
|||
|
if ( TftpSecurityHandle != 0 ) {
|
|||
|
TftpLogoff(NetServerIpAddress, TftpSecurityHandle);
|
|||
|
TftpSecurityHandle = 0;
|
|||
|
}
|
|||
|
#endif // defined(REMOTE_BOOT_SECURITY)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// let's not set the receive status if the card isn't active.
|
|||
|
//
|
|||
|
RomSetReceiveStatus( 0 );
|
|||
|
#endif // defined(_X86_)
|
|||
|
|
|||
|
|
|||
|
#ifdef EFI
|
|||
|
extern VOID EfiNetTerminate();
|
|||
|
EfiNetTerminate();
|
|||
|
#endif
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // NetTerminate
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetArcClose (
|
|||
|
IN ULONG FileId
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetArcClose\n") );
|
|||
|
|
|||
|
if ( FileId != NET_DEVICE_ID ) {
|
|||
|
return NetRealArcCloseRoutine( FileId );
|
|||
|
}
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
} // NetArcClose
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetArcOpen (
|
|||
|
IN CHAR * FIRMWARE_PTR OpenPath,
|
|||
|
IN OPEN_MODE OpenMode,
|
|||
|
OUT ULONG * FIRMWARE_PTR FileId
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetArcOpen\n") );
|
|||
|
|
|||
|
if ( _strnicmp(OpenPath, "net(", 4) != 0 ) {
|
|||
|
return NetRealArcOpenRoutine( OpenPath, OpenMode, FileId );
|
|||
|
}
|
|||
|
|
|||
|
*FileId = NET_DEVICE_ID;
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
} // NetArcOpen
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetClose (
|
|||
|
IN ULONG FileId
|
|||
|
)
|
|||
|
{
|
|||
|
PBL_FILE_TABLE fileTableEntry;
|
|||
|
DPRINT( TRACE, ("NetClose FileId = %d\n", FileId) );
|
|||
|
|
|||
|
fileTableEntry = &BlFileTable[FileId];
|
|||
|
|
|||
|
{
|
|||
|
DPRINT( REAL_LOUD, ("NetClose: id %d, freeing memory at 0x%08x, %d bytes\n",
|
|||
|
FileId,
|
|||
|
fileTableEntry->u.NetFileContext.InMemoryCopy,
|
|||
|
fileTableEntry->u.NetFileContext.FileSize) );
|
|||
|
BlFreeDescriptor( (ULONG)((ULONG_PTR)fileTableEntry->u.NetFileContext.InMemoryCopy >> PAGE_SHIFT ));
|
|||
|
|
|||
|
//
|
|||
|
// If the data read for this specific open was what was cached,
|
|||
|
// then mark the cache empty.
|
|||
|
//
|
|||
|
if (fileTableEntry->u.NetFileContext.InMemoryCopy == CachedFileData) {
|
|||
|
CachedFileData = NULL;
|
|||
|
CachedFilePath[0] = '\0';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fileTableEntry->Flags.Open = 0;
|
|||
|
|
|||
|
return EROFS;
|
|||
|
|
|||
|
} // NetClose
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetMount (
|
|||
|
IN CHAR * FIRMWARE_PTR MountPath,
|
|||
|
IN MOUNT_OPERATION Operation
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetMount\n") );
|
|||
|
|
|||
|
return EROFS;
|
|||
|
|
|||
|
} // NetMount
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetOpen (
|
|||
|
IN CHAR * FIRMWARE_PTR OpenPath,
|
|||
|
IN OPEN_MODE OpenMode,
|
|||
|
OUT ULONG * FIRMWARE_PTR FileId
|
|||
|
)
|
|||
|
{
|
|||
|
NTSTATUS ntStatus;
|
|||
|
ARC_STATUS arcStatus; // holds temp values, not the function return value
|
|||
|
PBL_FILE_TABLE fileTableEntry;
|
|||
|
TFTP_REQUEST request;
|
|||
|
ULONG oldBase;
|
|||
|
ULONG oldLimit;
|
|||
|
PCHAR p;
|
|||
|
#if defined(REMOTE_BOOT_SECURITY)
|
|||
|
static BOOLEAN NetBootTryTftpSecurity = FALSE;
|
|||
|
#endif // defined(REMOTE_BOOT_SECURITY)
|
|||
|
|
|||
|
DPRINT( TRACE, ("NetOpen FileId = %d\n", *FileId) );
|
|||
|
|
|||
|
DPRINT( LOUD, ("NetOpen: opening %s, id %d, mode %d\n", OpenPath, *FileId, OpenMode) );
|
|||
|
fileTableEntry = &BlFileTable[*FileId];
|
|||
|
|
|||
|
if ( OpenMode != ArcOpenReadOnly ) {
|
|||
|
DPRINT( LOUD, ("NetOpen: invalid OpenMode\n") );
|
|||
|
return EROFS;
|
|||
|
}
|
|||
|
|
|||
|
fileTableEntry->Flags.Open = 1; // Prevent GetCSCFileNameFromUNCPath using our entry
|
|||
|
|
|||
|
#if defined(REMOTE_BOOT_SECURITY)
|
|||
|
//
|
|||
|
// Login if we don't have a valid handle, using the on-disk secret.
|
|||
|
//
|
|||
|
|
|||
|
if ((TftpSecurityHandle == 0) &&
|
|||
|
NetBootTryTftpSecurity) {
|
|||
|
|
|||
|
ULONG FileId;
|
|||
|
RI_SECRET Secret;
|
|||
|
UCHAR Domain[RI_SECRET_DOMAIN_SIZE + 1];
|
|||
|
UCHAR User[RI_SECRET_USER_SIZE + 1];
|
|||
|
struct {
|
|||
|
UCHAR Owf[LM_OWF_PASSWORD_SIZE+NT_OWF_PASSWORD_SIZE];
|
|||
|
} Passwords[2];
|
|||
|
UCHAR Sid[RI_SECRET_SID_SIZE];
|
|||
|
|
|||
|
arcStatus = BlOpenRawDisk(&FileId);
|
|||
|
|
|||
|
if (arcStatus == ESUCCESS) {
|
|||
|
|
|||
|
arcStatus = BlReadSecret(FileId, &Secret);
|
|||
|
if (arcStatus == ESUCCESS) {
|
|||
|
BlParseSecret(
|
|||
|
Domain,
|
|||
|
User,
|
|||
|
Passwords[0].Owf,
|
|||
|
Passwords[0].Owf + LM_OWF_PASSWORD_SIZE,
|
|||
|
Passwords[1].Owf,
|
|||
|
Passwords[1].Owf + LM_OWF_PASSWORD_SIZE,
|
|||
|
Sid,
|
|||
|
&Secret);
|
|||
|
DPRINT(LOUD, ("Logging on to <%s><%s>\n", Domain, User));
|
|||
|
|
|||
|
//
|
|||
|
// Try logging on with the first password, if that fails
|
|||
|
// then try the second.
|
|||
|
//
|
|||
|
|
|||
|
ntStatus = TftpLogin(
|
|||
|
Domain,
|
|||
|
User,
|
|||
|
Passwords[0].Owf,
|
|||
|
NetServerIpAddress,
|
|||
|
&TftpSecurityHandle);
|
|||
|
if (!NT_SUCCESS(ntStatus)) {
|
|||
|
DPRINT(LOUD, ("TftpLogin using password 2\n"));
|
|||
|
ntStatus = TftpLogin(
|
|||
|
Domain,
|
|||
|
User,
|
|||
|
Passwords[1].Owf,
|
|||
|
NetServerIpAddress,
|
|||
|
&TftpSecurityHandle);
|
|||
|
if (NT_SUCCESS(ntStatus)) {
|
|||
|
NetBootTftpUsedPassword2 = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
|
|||
|
}
|
|||
|
|
|||
|
arcStatus = BlCloseRawDisk(FileId);
|
|||
|
|
|||
|
//
|
|||
|
// We are inside the if() for successfully opening the raw
|
|||
|
// disk, so we are not diskless. On these machines we must
|
|||
|
// fail the open at this point.
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS(ntStatus)) {
|
|||
|
DPRINT( ERROR, ("TftpLogin failed %lx\n", ntStatus) );
|
|||
|
return EACCES;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
NetBootTryTftpSecurity = FALSE; // so we don't try to open it again
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
#endif // defined(REMOTE_BOOT_SECURITY)
|
|||
|
|
|||
|
DPRINT( LOUD, ("NetOpen: opening %s\n", OpenPath) );
|
|||
|
|
|||
|
oldBase = BlUsableBase;
|
|||
|
oldLimit = BlUsableLimit;
|
|||
|
BlUsableBase = BL_DRIVER_RANGE_LOW;
|
|||
|
BlUsableLimit = BL_DRIVER_RANGE_HIGH;
|
|||
|
|
|||
|
//
|
|||
|
// If this request matches the cached file, then just copy that data.
|
|||
|
//
|
|||
|
|
|||
|
if ((fileTableEntry->DeviceId == CachedFileDeviceId) &&
|
|||
|
(strcmp(OpenPath, CachedFilePath) == 0) &&
|
|||
|
(CachedFileData != NULL)) {
|
|||
|
|
|||
|
ULONG basePage;
|
|||
|
|
|||
|
arcStatus = BlAllocateAlignedDescriptor(
|
|||
|
LoaderFirmwareTemporary,
|
|||
|
0,
|
|||
|
(CachedFileSize + PAGE_SIZE - 1) >> PAGE_SHIFT,
|
|||
|
0,
|
|||
|
&basePage
|
|||
|
);
|
|||
|
|
|||
|
BlUsableBase = oldBase;
|
|||
|
BlUsableLimit = oldLimit;
|
|||
|
|
|||
|
if ( arcStatus != ESUCCESS ) {
|
|||
|
fileTableEntry->Flags.Open = 0; // Free entry we didn't use
|
|||
|
|
|||
|
return EROFS;
|
|||
|
}
|
|||
|
|
|||
|
DPRINT( REAL_LOUD, ("NetOpen: Using cache for file %s\n", CachedFilePath) );
|
|||
|
|
|||
|
fileTableEntry->u.NetFileContext.InMemoryCopy = (PUCHAR)ULongToPtr( (basePage << PAGE_SHIFT) );
|
|||
|
memcpy(fileTableEntry->u.NetFileContext.InMemoryCopy, CachedFileData, CachedFileSize);
|
|||
|
fileTableEntry->u.NetFileContext.FileSize = CachedFileSize;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
request.RemoteFileName = OpenPath;
|
|||
|
request.ServerIpAddress = NetServerIpAddress;
|
|||
|
request.MemoryAddress = NULL;
|
|||
|
request.MaximumLength = 0;
|
|||
|
request.BytesTransferred = 0xbadf00d;
|
|||
|
request.Operation = TFTP_RRQ;
|
|||
|
request.MemoryType = LoaderFirmwareTemporary;
|
|||
|
#if defined(REMOTE_BOOT_SECURITY)
|
|||
|
request.SecurityHandle = TftpSecurityHandle;
|
|||
|
#endif // defined(REMOTE_BOOT_SECURITY)
|
|||
|
request.ShowProgress = FALSE;
|
|||
|
|
|||
|
ntStatus = TftpGetPut( &request );
|
|||
|
DPRINT( REAL_LOUD, ("NetOpen: TftpGetPut(get) status: %x, bytes: %x\n", ntStatus, request.BytesTransferred) );
|
|||
|
|
|||
|
BlUsableBase = oldBase;
|
|||
|
BlUsableLimit = oldLimit;
|
|||
|
|
|||
|
if ( !NT_SUCCESS(ntStatus) ) {
|
|||
|
if ( request.MemoryAddress != NULL ) {
|
|||
|
DPRINT( REAL_LOUD, ("NetOpen: freeing memory at 0x%08x, %d bytes\n",
|
|||
|
request.MemoryAddress, request.MaximumLength) );
|
|||
|
BlFreeDescriptor( (ULONG)((ULONG_PTR)request.MemoryAddress >> PAGE_SHIFT ));
|
|||
|
}
|
|||
|
fileTableEntry->Flags.Open = 0; // Free entry we didn't use
|
|||
|
|
|||
|
if ( ntStatus == STATUS_INSUFFICIENT_RESOURCES ) {
|
|||
|
return ENOMEM;
|
|||
|
}
|
|||
|
return EROFS;
|
|||
|
}
|
|||
|
|
|||
|
fileTableEntry->u.NetFileContext.FileSize = request.BytesTransferred;
|
|||
|
fileTableEntry->u.NetFileContext.InMemoryCopy = request.MemoryAddress;
|
|||
|
|
|||
|
//
|
|||
|
// We always cache the last file that was actually read from
|
|||
|
// the network.
|
|||
|
//
|
|||
|
|
|||
|
strcpy(CachedFilePath, OpenPath);
|
|||
|
CachedFileDeviceId = fileTableEntry->DeviceId;
|
|||
|
CachedFileSize = request.BytesTransferred;
|
|||
|
CachedFileData = request.MemoryAddress;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
fileTableEntry->Position.QuadPart = 0;
|
|||
|
|
|||
|
fileTableEntry->Flags.Read = 1;
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
} // NetOpen
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetRead (
|
|||
|
IN ULONG FileId,
|
|||
|
OUT VOID * FIRMWARE_PTR Buffer,
|
|||
|
IN ULONG Length,
|
|||
|
OUT ULONG * FIRMWARE_PTR Count
|
|||
|
)
|
|||
|
{
|
|||
|
PBL_FILE_TABLE fileTableEntry;
|
|||
|
PNET_FILE_CONTEXT context;
|
|||
|
PUCHAR source;
|
|||
|
|
|||
|
fileTableEntry = &BlFileTable[FileId];
|
|||
|
context = &fileTableEntry->u.NetFileContext;
|
|||
|
|
|||
|
{
|
|||
|
source = context->InMemoryCopy + fileTableEntry->Position.LowPart;
|
|||
|
if ( (fileTableEntry->Position.LowPart + Length) > context->FileSize ) {
|
|||
|
Length = context->FileSize - fileTableEntry->Position.LowPart;
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyMemory( Buffer, source, Length );
|
|||
|
*Count = Length;
|
|||
|
|
|||
|
fileTableEntry->Position.LowPart += Length;
|
|||
|
}
|
|||
|
|
|||
|
DPRINT( REAL_LOUD, ("NetRead: id %d, length %d, count %d, new pos %x\n",
|
|||
|
FileId, Length, *Count, fileTableEntry->Position.LowPart) );
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
} // NetRead
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetGetReadStatus (
|
|||
|
IN ULONG FileId
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetGetReadStatus\n") );
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
} // NetGetReadStatus
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetSeek (
|
|||
|
IN ULONG FileId,
|
|||
|
IN LARGE_INTEGER * FIRMWARE_PTR Offset,
|
|||
|
IN SEEK_MODE SeekMode
|
|||
|
)
|
|||
|
{
|
|||
|
PBL_FILE_TABLE fileTableEntry;
|
|||
|
LARGE_INTEGER newPosition;
|
|||
|
|
|||
|
//DPRINT( TRACE, ("NetSeek\n") );
|
|||
|
|
|||
|
fileTableEntry = &BlFileTable[FileId];
|
|||
|
|
|||
|
{
|
|||
|
if ( SeekMode == SeekAbsolute ) {
|
|||
|
newPosition = *Offset;
|
|||
|
} else if ( SeekMode == SeekRelative ) {
|
|||
|
newPosition.QuadPart =
|
|||
|
fileTableEntry->Position.QuadPart + Offset->QuadPart;
|
|||
|
} else {
|
|||
|
return EROFS;
|
|||
|
}
|
|||
|
|
|||
|
DPRINT( REAL_LOUD, ("NetSeek: id %d, mode %d, offset %x, new pos %x\n",
|
|||
|
FileId, SeekMode, Offset->LowPart, newPosition.LowPart) );
|
|||
|
|
|||
|
if ( newPosition.QuadPart > fileTableEntry->u.NetFileContext.FileSize ) {
|
|||
|
return EROFS;
|
|||
|
}
|
|||
|
|
|||
|
fileTableEntry->Position = newPosition;
|
|||
|
}
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
} // NetSeek
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetWrite (
|
|||
|
IN ULONG FileId,
|
|||
|
IN VOID * FIRMWARE_PTR Buffer,
|
|||
|
IN ULONG Length,
|
|||
|
OUT ULONG * FIRMWARE_PTR Count
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetWrite\n") );
|
|||
|
|
|||
|
return EROFS;
|
|||
|
|
|||
|
} // NetWrite
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetGetFileInformation (
|
|||
|
IN ULONG FileId,
|
|||
|
OUT FILE_INFORMATION * FIRMWARE_PTR Buffer
|
|||
|
)
|
|||
|
{
|
|||
|
PBL_FILE_TABLE fileTableEntry;
|
|||
|
//DPRINT( TRACE, ("NetGetFileInformation\n") );
|
|||
|
|
|||
|
fileTableEntry = &BlFileTable[FileId];
|
|||
|
|
|||
|
{
|
|||
|
Buffer->EndingAddress.QuadPart = fileTableEntry->u.NetFileContext.FileSize;
|
|||
|
Buffer->CurrentPosition.QuadPart = fileTableEntry->Position.QuadPart;
|
|||
|
DPRINT( REAL_LOUD, ("NetGetFileInformation returning size %x, position %x\n",
|
|||
|
Buffer->EndingAddress.LowPart, Buffer->CurrentPosition.LowPart) );
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
} // NetGetFileInformation
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetSetFileInformation (
|
|||
|
IN ULONG FileId,
|
|||
|
IN ULONG AttributeFlags,
|
|||
|
IN ULONG AttributeMask
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetSetFileInformation\n") );
|
|||
|
|
|||
|
return EROFS;
|
|||
|
|
|||
|
} // NetSetFileInformation
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetRename (
|
|||
|
IN ULONG FileId,
|
|||
|
IN CHAR * FIRMWARE_PTR NewFileName
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetRename\n") );
|
|||
|
|
|||
|
return EROFS;
|
|||
|
|
|||
|
} // NetRename
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
NetGetDirectoryEntry (
|
|||
|
IN ULONG FileId,
|
|||
|
IN DIRECTORY_ENTRY * FIRMWARE_PTR DirEntry,
|
|||
|
IN ULONG NumberDir,
|
|||
|
OUT ULONG * FIRMWARE_PTR CountDir
|
|||
|
)
|
|||
|
{
|
|||
|
DPRINT( TRACE, ("NetGetDirectoryEntry\n") );
|
|||
|
|
|||
|
return EROFS;
|
|||
|
|
|||
|
} // NetGetDirectoryEntry
|
|||
|
|
|||
|
|