diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/boot/veneer/vrio.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/boot/veneer/vrio.c')
-rw-r--r-- | private/ntos/boot/veneer/vrio.c | 1425 |
1 files changed, 1425 insertions, 0 deletions
diff --git a/private/ntos/boot/veneer/vrio.c b/private/ntos/boot/veneer/vrio.c new file mode 100644 index 000000000..c0a1bd2ae --- /dev/null +++ b/private/ntos/boot/veneer/vrio.c @@ -0,0 +1,1425 @@ +/* + * + * Copyright (c) 1995 FirePower Systems, Inc. + * Copyright (c) 1994 FirePower Systems Inc. + * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved. + * + * $RCSfile: vrio.c $ + * $Revision: 1.9 $ + * $Date: 1996/04/15 02:55:53 $ + * $Locker: $ + * + * + * Module Name: + * vrio.c + * + * Author: + * Shin Iwamoto at FirePower Systems Inc. + * + * History: + * 26-Sep-94 Shin Iwamoto at FirePower Systems Inc. + * Added checking SeekMode in VrSeek(). + * 15-Sep-94 Shin Iwamoto at FirePower Systems Inc. + * Added saving the area pointed to by OpenPath in VrOpen(). + * 15-Jul-94 Shin Iwamoto at FirePower Systems Inc. + * Added for XXX_SEEK_IS_BUSTED in VrSeek(). + * 14-Jul-94 Shin Iwamoto at FirePower Systems Inc. + * Added ONE_IO_SIZE in VrRead() and VrWrite(). + * 13-Jul-94 Shin Iwamoto at FirePower Systems Inc. + * Added ENOSPC checking in VrWrite(). + * Added for reading ahead in VrGetReadStatus() and VrRead(). + * 11-Jul-94 Shin Iwamoto at FirePower Systems Inc. + * Added some debugging facilities in VrOpen. These were + * from checked-in veneer source code. + * 16-Jun-94 Shin Iwamoto at FirePower Systems Inc. + * Added when a serial device doesn't read in VrRead(). + * 15-Jun-94 Shin Iwamoto at FirePower Systems Inc. + * When OpenPath inclues console, the path is for a device. + * So, FilePath was set to null. + * 13-Jun-94 Shin Iwamoto at FirePower Systems Inc. + * Added debugging statements. + * Modified some porting from Mike Tooch at FirmWorks. + * 18-May-94 Shin Iwamoto at FirePower Systems Inc. + * Added for unsinged long size in VrWrite. + * Added a part of VrMount. + * Added that DirectoryFile flag is ignored in + * VrSetFileInformation(). + * Added for Delete flag in FileTable in + * VrRead(), VrWrite(), VrSeek(), VrGetReadStatus() + * Added some comments. + * and VrSetFileInformation(). + * 17-May-94 Shin Iwamoto at FirePower Systems Inc. + * Added for NetworkDevice in GetDeviceAttribute(). + * Added for unsinged long size in VrRead. + * 12-May-94 Shin Iwamoto at FirePower Systems Inc. + * Changed the name, strlen and strncmp to + * VfStrlen and VfStrncmp. + * 11-May-94 Shin Iwamoto at FirePower Systems Inc. + * Added FIleTable. Changed rootnode to RootNode. + * Put cast PCAHR to the first parameter of bzero. + * Changed OFPhandle to OfPhandle. + * Changed the name of VrFindCOnfigurationNode. + * 10-May-94 Shin Iwamoto at FirePower Systems Inc. + * Changed Vr{Open|Close|Read|Write|Seek} because of + * changing the file table structure. + * 05-May-94 Shin Iwamoto at FirePower Systems Inc. + * Created. + * + */ + + +#include "veneer.h" + +// +// Some switches +// + +#define MAX_OPEN_PATH_SIZE MAX_PATH_NAME_SIZE +#define ONE_IO_SIZE 1024*1024 + +#define ZERO_LARGE 0 +#define NOT_ZERO_LARGE 1 + +#define Minimum(X,Y) ((X) < (Y) ? (X) : (Y)) + + +// +// File Table definition +// +FILE_TABLE_ENTRY FileTable[FILE_TABLE_SIZE]; + + +// +// Function declarations +// +STATIC ARC_STATUS +GetFileTableEntry( + OUT PULONG + ); +STATIC ARC_STATUS +GetDeviceAttribute( + IN ULONG, + IN PCONFIGURATION_NODE + ); +STATIC VOID +AddLargeInt( + PLARGE_INTEGER, + PLARGE_INTEGER + ); +STATIC VOID +MoveLargeInt( + PLARGE_INTEGER, + PLARGE_INTEGER + ); +STATIC LONG +IsLarge( + PLARGE_INTEGER + ); +STATIC VOID +DecrementLarge( + PLARGE_INTEGER + ); + + + +/* + * Name: VrOpen + * + * Description: + * This function opens the file specified by OpenPath. + * The pathname is translated into the devicename for Open Firmware, + * then OFOpen is called with the devicename. + * + * Arguments: + * OpenPath - ARC compliant pathname of the device/file to be opened. + * OpenMode - Supplies the mode in which the file is opened. + * FileId - Pointer to a variable that receives the fileid for + * this pathname. + * + * Return Value: + * If the file is successfully opened returns ESUCCESS otherwise + * returns an unsuccessful status. + * + */ +ARC_STATUS +VrOpen( + IN PCHAR OpenPath, + IN OPEN_MODE OpenMode, + OUT PULONG FileId + ) +{ + PCHAR FilePath, DevicePath, Partition, Console; + ihandle IHandle; + ARC_STATUS Status; + PCONFIGURATION_NODE ConfNode; + PCHAR pstr1; + LONG DevSpecLen; + + debug(VRDBG_OPEN, "VrOpen: Entry - Path: %s Mode: %x\n", + OpenPath, OpenMode); + + if (strlen(OpenPath) >= MAX_OPEN_PATH_SIZE) { + debug(VRDBG_OPEN, "VrOpen: ENAMETOOLONG: '%s'\n", OpenPath); + return ENAMETOOLONG; + } + + // + // Find Partition, Console and FilePath in OpenPath. + // + FilePath = NULL; + Partition = NULL; + Console = NULL; + for (pstr1 = OpenPath; *pstr1; pstr1++) { + if (strncmp(pstr1, "partition", 9) == 0) { + Partition = pstr1; + while (*pstr1++ != ')') { + ; + } + FilePath = pstr1; + break; + } else if (strncmp(pstr1, "console", 7) == 0) { + Console = pstr1; + while (*pstr1++ != ')') { + ; + } + if (*pstr1 != '\0') { + return EINVAL; + } + FilePath = NULL; // Console is a device. + break; + } + else if (*pstr1 == ')') { + FilePath = pstr1+1; + } + } + // + // Did we eventually wind up with a FilePath after all? + // + if ((FilePath != NULL) && (strlen(FilePath) == 0)) { + FilePath = NULL; + } + debug(VRDBG_OPEN, "VrOpen: Partition '%s' FilePath '%s'\n", + Partition == NULL ? "NULL" : Partition, + FilePath == NULL ? "NULL" : FilePath); + + // + // Check open mode for a device. + // + if ((FilePath == NULL) && (OpenMode > ArcOpenReadWrite)) { + debug(VRDBG_OPEN, "VrOpen: EINVAL: '%s'\n", OpenPath); + return EINVAL; + } + + // + // Extract the device name from OpenPath. + // + ConfNode = ArcPathToNode(OpenPath); + if (ConfNode == NULL) { + debug(VRDBG_OPEN, "VrOpen: ENODEV: '%s'\n", OpenPath); + return ENODEV; + } + + // + // Translate the device name into the device path for Open Firmware. + // Add space for the partition and file components. + // + pstr1 = NodeToPath(ConfNode); + DevSpecLen = strlen(pstr1) + 16; // Enough for a partition specifier. + if (FilePath != NULL) { + DevSpecLen += strlen(FilePath); + } + DevicePath = zalloc(DevSpecLen); + strcpy(DevicePath, pstr1); + free(pstr1); + + // + // Get a free entry in the file table. + // + if (Status = GetFileTableEntry(FileId)) { + debug(VRDBG_OPEN, "VrOpen: GetFileTableEntry returned %x\n", Status); + return Status; + } + + // + // Set flags in the FileTable. + // + if (Status = GetDeviceAttribute(*FileId, ConfNode)) { + debug(VRDBG_OPEN, "VrOpen: GetDeviceAttribute returned %x\n", Status); + return Status; + } + + if ((Partition == NULL) && (FilePath == NULL)) { // A device (not file) + FileTable[*FileId].Flags.Device = 1; + strcat(DevicePath, ":0"); + } else { // A file (not a device) + // + // Convert the partition and the filename (if they exist) as follows: + // + // [partition(key1)][<filepath>] + // --> :[key1][,<filepath>] + // + strcat(DevicePath, ":"); + if (Partition != NULL) { + FileTable[*FileId].Flags.Partition = (FilePath == NULL); + pstr1 = Partition; + while (*pstr1++ != '(') { + ; + } + if (*pstr1 == ')') { + strcat(DevicePath, "0"); + } else { + PCHAR pstr2; + + pstr2 = DevicePath + strlen(DevicePath); + do { + *pstr2++ = *pstr1++; + } while (*pstr1 != ')'); + *pstr2 = '\0'; + } + } + if (FilePath != NULL) { + strcat(DevicePath, ","); + strcat(DevicePath, FilePath); + } + } + + // + // Now we can open the device path (including the file path). + // + IHandle = OFOpen(DevicePath); + debug(VRDBG_OPEN, "OFOpen: IHandle: %x\n", IHandle); + FileTable[*FileId].PathName = DevicePath; + + // + // Checking related to OpenMode. + // + switch (OpenMode) { + case ArcCreateWriteOnly: + case ArcCreateReadWrite: + if (IHandle != 0) { + (VOID)OFClose(IHandle); + return EACCES; + } + break; + default: + if (IHandle == 0) { + return EIO; + } + } + + FileTable[*FileId].Flags.Open = 1; + FileTable[*FileId].IHandle = IHandle; + + debug(VRDBG_OPEN, "VrOpen: Exit - FileId: %d IHandle: %x\n", + *FileId, IHandle); + + return ESUCCESS; +} + + +/* + * Name: VrClose + * + * Description: + * This function closes a file or a device if it is opened. + * + * Arguments: + * FileId - Supplies the file table index. + * + * Return Value: + * If the specified file is open, then a close is attempted via + * OFClose and ESUCCESS is returned. Otherwise, return an unsuccessful + * status. + * + */ +ARC_STATUS +VrClose( + IN ULONG FileId + ) +{ + debug(VRDBG_OPEN, "VrClose: Entry - FileId: %d\n", FileId); + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (FileTable[FileId].Flags.Open != 1) { + return EACCES; + } + + // + // Close the file. + // + (VOID)OFClose(FileTable[FileId].IHandle); + + // + // Release the file table entry. + // + // FileTable[FileId].Flags.Open = 0; + bzero((PCHAR)&FileTable[FileId], sizeof(FILE_TABLE_ENTRY)); + free(FileTable[FileId].PathName); + + debug(VRDBG_OPEN, "VrClose: Exit\n"); + + return ESUCCESS; +} + + +/* + * Name: VrRead + * + * Description: + * This function reads data from the device of file specified by FileId + * into the buffer pointed to by Buffer. + * + * Arguments: + * FileId - Supplies the file table index. + * Buffer - Supplies a pointer to the buffer that receives the read + * data. + * Length - Supplies the maximum number of bytes to be read. + * If this field contains the value zero, then no bytes + * are read. + * Count - Supplies a pointer to a variable that receives the number + * of bytes actually transfered. + * + * Return Value: + * If the specified file is open for read, then a read is attempted + * and the status of the operation is retuned. Otherwise, return + * an unsuccessful status. + * + */ + +STATIC CHAR consin_readahead = 0; + +ARC_STATUS +VrRead( + IN ULONG FileId, + OUT PVOID Buffer, + IN ULONG Length, + OUT PULONG Count + ) +{ + LARGE_INTEGER LInteger; + PCHAR buf = (PCHAR) Buffer; + + if (FileId == 0) { // stdin + if (consin_readahead) { + *buf = consin_readahead; + consin_readahead = 0; + *Count = 1; + } else { + if (ConsoleIn == 0) { + (void) VrFindConsolePath("stdin"); + } + while (((LONG)*Count = OFRead(ConsoleIn, Buffer, Length)) <= 0){ + ; + } + } + return ESUCCESS; + } + + debug(VRDBG_RDWR, "VrRead: Entry - FileId: %d Buf: %x len: %d\n", + FileId, Buffer, Length); + + // + // If Length is zero, return as if the function were successful. + // + if (Length == 0) { + *Count = 0; + return ESUCCESS; + } + if (FileId == 1) { + return EBADF; + } + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (!(FileTable[FileId].Flags.Open == 1 + && FileTable[FileId].Flags.Read == 1)) { + return EACCES; + } + if (FileTable[FileId].Flags.Delete == 1) { + return EACCES; + } + +#ifdef NO_UNSIGNED_LONG_IO + // + // Calls the read routine. + // + (LONG)*Count = OFRead(FileTable[FileId].IHandle, Buffer, Length); + if ((LONG)*Count == -1) { + return EIO; // XXXX + } + +#else // NO_UNSIGNED_LONG_IO + // + // Initialize Counter. + // + *Count = 0; + + // + // Checking read ahead buffer. If already read, the copy the buffer + // into Buffer. + // + if (FileTable[FileId].ReadAheadCount != 0) { + *Count = FileTable[FileId].ReadAheadCount; + bcopy(FileTable[FileId].ReadAheadBuffer, Buffer, *Count); + Buffer = (PCHAR)Buffer + *Count; + Length -= *Count; + FileTable[FileId].ReadAheadCount = 0; + } + + // + // Calls the read routine. + // + while (Length > 0) { + LONG SingleReadSize; + LONG ReadCount; + + SingleReadSize = Minimum(Length, ONE_IO_SIZE); + ReadCount = OFRead(FileTable[FileId].IHandle, Buffer, SingleReadSize); + if (ReadCount == -1) { + LONG Status; + + // + // If an error in the second or later read happes, + // the offset must be put back using OFSeek. + // In reading ahead, this is useful. + // + if (*Count != 0) { + Status = OFSeek(FileTable[FileId].IHandle, + FileTable[FileId].Position.HighPart, + FileTable[FileId].Position.LowPart); + // + // Ignore Status. + // + } + return EIO; // XXXX + } + + // + // Retry to read, when the device is serial and there is no data. + // + if ((ReadCount == -2) && (*Count == 0)) { + continue; + } + + // + // Update the number of bytes read successfully. + // + *Count += ReadCount; + + // + // If the device represented by FileId is a network device, + // read one time. If not yet read, continue. + // + if (FileTable[FileId].Flags.NetworkDevice == 1) { + if ((ReadCount == 0) && (*Count == 0)) { + continue; + } + return ESUCCESS; + } + + // + // Find EOF, then break this loop. + // + if (ReadCount < SingleReadSize) { + break; + } + + // + // Update the remaining length and the buffer to point to + // the next position. + // + Length -= SingleReadSize; + Buffer = (PCHAR)Buffer + SingleReadSize; + } +#endif // NO_UNSIGNED_LONG_IO + + // + // Calculates the position of the file. + // + LInteger.HighPart = 0; + LInteger.LowPart = *Count; + AddLargeInt(&FileTable[FileId].Position, &LInteger); + + debug(VRDBG_RDWR, "VrRead: Exit ReadCount: %d\n", *Count); + + return ESUCCESS; +} + + +/* + * Name: VrWrite + * + * Description: + * This function writes data from memory starting from the buffer + * pointed to by Buffer to the device specified by FileId. + * Upon completion of a successful write, the byte offset for FileId + * is updated; otherwise the byte offset is left unchanged. + * + * Arguments: + * FileId - Supplies the file table index. + * Buffer - Supplies a pointer to the buffer that contains + * the write data. + * Length - Supplies the number of bytes to be written. + * Count - Supplies a pointer to a variable that contains + * the number of bytes actually transfered. + * + * Return Value: + * If the specified file is open for write, then a write is attempted + * using OFWrite and a status is returned. Otherwise, return + * an unsuccessful status. + * + */ +ARC_STATUS +VrWrite( + IN ULONG FileId, + IN PVOID Buffer, + IN ULONG Length, + OUT PULONG Count + ) +{ + LARGE_INTEGER LInteger; + ARC_STATUS Status; + + if (FileId == 1) { // stdout + *Count = OFWrite(ConsoleOut, Buffer, Length); + return ESUCCESS; + } + + debug(VRDBG_RDWR, "VrWrite: Entry - FileId: %d Buf: %x len: %d\n", + FileId, Buffer, Length); + + // + // If Length is zero, return as if the function were successful. + // + if (Length == 0) { + *Count = 0; + return ESUCCESS; + } + if (FileId == 0) { + return EBADF; + } + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (!(FileTable[FileId].Flags.Open == 1 + && FileTable[FileId].Flags.Write == 1)) { + return EACCES; + } + if (FileTable[FileId].Flags.Delete == 1) { + return EACCES; + } + + // + // If Length bytes cannot be placed into a network packet, + // return ENOSPC without sending the packet, placing the number of bytes + // that could be written in Count. + // + if (FileTable[FileId].Flags.NetworkDevice == 1) { + ULONG MaxFrameSize; + + MaxFrameSize = get_int_prop(OFFinddevice(FileTable[FileId].PathName), + "max-frame-size"); + if (Length > MaxFrameSize) { + *Count = MaxFrameSize; + return ENOSPC; + } + } + +#ifdef NO_UNSIGNED_LONG_IO + // + // Calls the write routine. + // + Status = ESUCCESS; + (LONG)*Count = OFWrite(FileTable[FileId].IHandle, Buffer, Length); + if ((LONG)*Count == -1) { + return EIO; // XXXX + } + +#else // NO_UNSIGNED_LONG_IO + + Status = ESUCCESS; + *Count = 0; + while (Length > 0) { + LONG SingleWriteSize; + LONG WriteCount; + + SingleWriteSize = Minimum(Length, ONE_IO_SIZE); + WriteCount = OFWrite(FileTable[FileId].IHandle, Buffer, + SingleWriteSize); + if (WriteCount == -1) { + LONG SeekStatus; + + // + // If an error in the second or later read happens, + // the offset must be put back using OFSeek. + // + if (*Count != 0) { + SeekStatus = OFSeek(FileTable[FileId].IHandle, + FileTable[FileId].Position.HighPart, + FileTable[FileId].Position.LowPart); + // + // Ignore Status. + // + } + return EIO; // XXXX + } + + // + // Update the number of bytes written successfully. + // + *Count += WriteCount; + + // + // If the device represented by FileId is a network device, + // write one time. If not yet written, continue. + // + if (FileTable[FileId].Flags.NetworkDevice == 1) { + if (WriteCount == 0) { + continue; + } + return ESUCCESS; + } + + // + // Find that the device is full. + // + if (WriteCount < SingleWriteSize) { + Status = ENOSPC; + break; + } + + // + // Update the remaining length and the buffer to point to + // the next position. + // + Length -= SingleWriteSize; + Buffer = (PCHAR)Buffer + SingleWriteSize; + } +#endif // NO_UNSIGNED_LONG_IO + + // + // Calculates the position of the file. + // + LInteger.HighPart = 0; + LInteger.LowPart = *Count; + AddLargeInt(&FileTable[FileId].Position, &LInteger); + + if (FileId >= 2) { + debug(VRDBG_RDWR, "VrWrite: Exit WrtCount: %d, Status: %d\n", + *Count, Status); + } + + return Status; +} + + +/* + * Name: VrMount + * + * Description: + * This function is used to load and unload media for devices that + * support removale media. + * + * Arguments: + * MountPath - Supplies a pointer to the variable that contains + * the path of the device. + * Operation - Supplies a indication whether the media is to be + * loaded or unloaded. + * + * Return Value: + * If the specified path is for device, then a mount is attempted + * a status is returned. Otherwise, return an unsuccessful status. + * + */ +ARC_STATUS +VrMount( + IN PCHAR MountPath, + IN MOUNT_OPERATION Operation + ) +{ + PCONFIGURATION_NODE ConfNode; + PCHAR FilePath, pstr1; + + debug(VRDBG_OPEN, "VrMount: Entry - MountPath: %s Operation: %d\n", + MountPath, Operation); + + // + // Check that the MountPath is a device. + // + FilePath = MountPath; + for (pstr1 = MountPath; *pstr1; pstr1++) { + if (strncmp(pstr1, "partition", 9) == 0) { + return EINVAL; + } else if (strncmp(pstr1, "console", 7) == 0) { + return EINVAL; + } else if (*pstr1 == ')') { + FilePath = pstr1+1; + } + } + if (FilePath == MountPath || FilePath[0] != '\0') { + return EINVAL; + } + + // + // Find the configuration node using the MountPath. + // + ConfNode = ArcPathToNode(MountPath); + if (ConfNode == NULL) { + return ENOENT; + } + + // + // Check that the device is removable. + // + if (!(ConfNode->Component.Flags.Removable)) { + return ENOENT; // XXXX + } + + // + // Translate the device name into the device path for Open Firmware. + // + // XXXX + // How do I mount/unmount ? + // If Operation is MountUnloadMedia for not mounted device, + // return ENXIO; + + debug(VRDBG_OPEN, "VrMount: Exit\n"); + + return ESUCCESS; +} + + +/* + * Name: VrSeek + * + * Description: + * This function changes the byte offset associated with the device, + * partition, or file specified by FileId. + * + * Arguments: + * FileId - Supplies the file table index. + * Offset - Supplies a poiner to a structure that contains + * the offset value. + * SeekMode - Supplies the type of positioning to be performed. + * + * Return Value: + * If the specified file is open, then a seek is attempted and + * the status of the operation is returned. Otherwise, return + * an unsuccessful status. + * + */ +ARC_STATUS +VrSeek( + IN ULONG FileId, + IN PLARGE_INTEGER Offset, + IN SEEK_MODE SeekMode + ) +{ + LONG Status; + + debug(VRDBG_RDWR, "VrSeek: Entry - FileId: %d Offset: %x.%x Mode: %x\n", + FileId, Offset->HighPart, Offset->LowPart, SeekMode); + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (FileTable[FileId].Flags.Open != 1) { + return EACCES; + } + if (FileTable[FileId].Flags.Delete == 1) { + return EACCES; + } + if (!(SeekMode == SeekRelative || SeekMode == SeekAbsolute)) { + return EINVAL; + } + + // + // If the specified device is Network, only set Offset into FileTable + // because the Offset is interpreted to be a count of input to ignore. + // The offset is cleared after reading the input packet. + // + if (FileTable[FileId].Flags.NetworkDevice == 1) { + (VOID)MoveLargeInt(&FileTable[FileId].Position, Offset); + return ESUCCESS; + } + + // + // Set the file position according to SeekMode. + // + if (SeekMode == SeekRelative) { + (VOID)AddLargeInt(&FileTable[FileId].Position, Offset); + } else { + (VOID)MoveLargeInt(&FileTable[FileId].Position, Offset); + } + + // + // If FileId is for Network device, the input packets are ignored + // according to Offset and then return with ESUCCESS. + // + if (FileTable[FileId].Flags.NetworkDevice == 1) { + while (IsLarge(&FileTable[FileId].Position) == NOT_ZERO_LARGE) { + LONG ReadSize; + CHAR Buffer[4]; + + if ((ReadSize = OFRead(FileTable[FileId].IHandle, Buffer, 1)) + == -1) { + return EIO; + } + if (ReadSize == 0) { + continue; + } + DecrementLarge(&FileTable[FileId].Position); + } + return ESUCCESS; + } + + Status = OFSeek(FileTable[FileId].IHandle, + FileTable[FileId].Position.HighPart, + FileTable[FileId].Position.LowPart); + if (Status == -1) { + return EINVAL; // XXXX + } + + debug(VRDBG_RDWR, "VrSeek: Exit\n"); + + return ESUCCESS; +} + + +/* + * Name: VrGetDirectoryEntry + * + * Description: + * This function reads directory entries from the system partition + * directory file specified by FileId. + * + * Arguments: + * FileId - Supplies the file table index. + * Buffer - Supplies a pointer to a buffer for the entry data. + * Length - Supplies the number of entries to retrieve. + * Count - Supplies a pointeer to the number of entries read + * into the buffer. + * + * Return Value: + * If the specified file is open for read, then the read is attempted + * and the status is returned. Otherwise, retrun an unsuccessful status. + * + */ +ARC_STATUS +VrGetDirectoryEntry( + IN ULONG FileId, + OUT PDIRECTORY_ENTRY Buffer, + IN ULONG Length, + OUT PULONG Count + ) +{ + debug(VRDBG_OPEN, "VrGetDirectoryEntry: Entry - FileId: %d Length: %d\n", + FileId, Length); + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (FileTable[FileId].Flags.Device) { + return ENOTDIR; + } + if (!(FileTable[FileId].Flags.Open == 1 + && FileTable[FileId].Flags.Read == 1)) { + return EBADF; + } + + // XXXX + // Get Director Entry if (FileID != directory) return ENOTDIR; + + debug(VRDBG_OPEN, "VrGetDirectoryEntry: Exit\n"); + + return ESUCCESS; +} + + +/* + * Name: VrGetFileInformation + * + * Description: + * This function retunrs an information structure about the specified + * file or partition. + * + * Arguments: + * FileId - Supplies the file table index. + * FileInformation - Supplies a pointer to the location of the file + * information data. + * + * Return Value: + * If the specified file is open, then getting the file information is + * attempted and the status is returned. Otherwise, retrun an unsuccessful + * status. + * + */ +ARC_STATUS +VrGetFileInformation( + IN ULONG FileId, + OUT PFILE_INFORMATION pFI + ) +{ + PFILE_TABLE_ENTRY fte; + ihandle ih; + PCONFIGURATION_NODE node; + ULONG size_thang[2]; + + debug(VRDBG_OPEN, "VrGetFileInformation: Entry - FileId: %d\n", FileId); + + if (FileId >= FILE_TABLE_SIZE) { + debug(VRDBG_OPEN, "VrGetFileInformation: Exit EBADF\n"); + return EBADF; + } + fte = &FileTable[FileId]; + if (fte->Flags.Open != 1) { + debug(VRDBG_OPEN, "VrGetFileInformation: Exit EACCES\n"); + return EACCES; + } + if (fte->Flags.Device == 1) { + debug(VRDBG_OPEN, "VrGetFileInformation: Exit EINVAL\n"); + return EINVAL; + } + + ih = fte->IHandle; + node = InstanceToNode(ih); + pFI->CurrentPosition = fte->Position; + pFI->Type = node->Component.Type; + + (void) OFCallMethod(2, 2, size_thang, "size", ih); + pFI->EndingAddress.HighPart = size_thang[0]; + pFI->EndingAddress.LowPart = size_thang[1]; + + if (fte->Flags.Partition == 1) { + (void) OFCallMethod( 1, 2, &(pFI->StartingAddress.HighPart), + "offset-high", ih); + (void) OFCallMethod( 1, 2, &(pFI->StartingAddress.LowPart), + "offset-low", ih); + AddLargeInt(&pFI->EndingAddress, &pFI->StartingAddress); + pFI->FileName[0] = '\0'; + pFI->FileNameLength = 0; + } else { + /* + * It's a file. + */ + pFI->StartingAddress.HighPart = 0; + pFI->StartingAddress.LowPart = 0; + strcpy(pFI->FileName, fte->PathName); // XXX s.b. strncpy(&,&,32) + pFI->FileNameLength = strlen(fte->PathName) + 1; + } +#ifdef XXX + pFI->Attributes = // Get this from the firmware, somehow. +#endif + debug(VRDBG_OPEN, "VrGetFileInformation:\n"); + debug(VRDBG_OPEN, "\tStarting %x.%x\n", pFI->StartingAddress.HighPart, + pFI->StartingAddress.LowPart); + debug(VRDBG_OPEN, "\tEnding %x.%x\n", pFI->EndingAddress.HighPart, + pFI->EndingAddress.LowPart); + debug(VRDBG_OPEN, "\tCurrent %x.%x\n", pFI->CurrentPosition.HighPart, + pFI->CurrentPosition.LowPart); + debug(VRDBG_OPEN, "\tType %d FileNameLength %d\n", pFI->Type, + pFI->FileNameLength); + debug(VRDBG_OPEN, "\tFileName '%s'\n", + pFI->FileNameLength ? pFI->FileName : "NULL"); + return ESUCCESS; +} + +/* + * Name: VrGetReadStatus + * + * Description: + * This function determines if any bytes would be returned if a read + * operation were performed on FileId. + * + * Arguments: + * FileId - Supplies the file table index. + * + * Return Value: + * If the specified file is open, then the getting read status is + * attempted and the status is returned. Otherwise, retrun an unsuccessful + * status. + * + */ +ARC_STATUS +VrGetReadStatus( + IN ULONG FileId + ) +{ + LONG Count; + + if (FileId == 0) { // stdin + if (consin_readahead != 0) { + return (ESUCCESS); + } + if (ConsoleIn == 0) { + (void) VrFindConsolePath("stdin"); + } + if (OFRead(ConsoleIn, &consin_readahead, 1) != 1) { + return (EAGAIN); + } + return (ESUCCESS); + } + + debug(VRDBG_RDWR, "VrGetReadStatus: Entry - FileId: %d\n", FileId); + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (!(FileTable[FileId].Flags.Open == 1 + && FileTable[FileId].Flags.Read == 1)) { + return EACCES; + } + if (FileTable[FileId].Flags.Delete == 1) { + return EACCES; + } + + // + // Try to read one byte. + // + Count = OFRead(FileTable[FileId].IHandle, + FileTable[FileId].ReadAheadBuffer, + 1); + if (Count != 1) { + FileTable[FileId].ReadAheadCount = 0; // For safety. + debug(VRDBG_RDWR, "VrGetReadStatus: Exit - with EAGAIN\n"); + return EAGAIN; + } + + // + // Now read ahead one byte. + // + FileTable[FileId].ReadAheadCount = 1; + + if (FileId >= 2) { + debug(VRDBG_RDWR, "VrGetReadStatus: Exit\n"); + } + + return ESUCCESS; +} + + +/* + * Name: VrSetFileInformation + * + * Description: + * This function sets the file attributes for the specified FileId. + * + * Arguments: + * FileId - Supplies the file table index. + * AttributeFlags - Supplies the attributes to be set for the file. + * AttributeMask - Supplies the attribute Mask. + * + * Return Value: + * If the specified file is open, then the setting file information is + * attempted and the status is returned. Otherwise, retrun an unsuccessful + * status. + * + */ +ARC_STATUS +VrSetFileInformation( + IN ULONG FileId, + IN ULONG AttributeFlags, + IN ULONG AttributeMask + ) +{ + debug(VRDBG_OPEN, "VrSetFileInformation: Entry - FileId: %d AttributeFlags: %x AttributeMask: %x\n", + FileId, AttributeFlags, AttributeMask); + + if (FileId >= FILE_TABLE_SIZE) { + return EBADF; + } + if (!(FileTable[FileId].Flags.Open == 1)) { + return EACCES; + } + if (FileTable[FileId].Flags.Device == 1) { + return EINVAL; + } + + // + // The attribute DirectoryFile is ignored for this function. + // + AttributeMask &= ~ArcDirectoryFile; + + // + // A file is marked for deletion by setting the DeleteFile flag + // in voth the AttributeFlags and AttributeMask parameters. + // In this case, the file can be access only by Close(). + // + if ((AttributeMask & ArcDeleteFile) && (AttributeFlags & ArcDeleteFile)) { + + // + // When the file is a derectroy which is not empty or a read-only file, + // EACCESS is retuned. + // + // XXXX not empy check is needed + // + if (!(FileTable[FileId].Flags.Read == 1 + && FileTable[FileId].Flags.Write == 0)) { + return EACCES; + } + + + FileTable[FileId].Flags.Delete = 1; + } + + // XXX return OFSetFileInformation(FileId, Buffer, Length, Count); + + debug(VRDBG_OPEN, "VrSetFileInformation: Exit\n"); + return(ESUCCESS); +} + + +/* + * Name: VrIoInitialize + * + * Description: + * This function initializes the I/O entry points in the firmware + * transfer vector and the file table. + * + * Arguments: + * None. + * + * Return Value: + * None. + * + */ +VOID +VrIoInitialize( + VOID + ) +{ + ULONG Index; + + // + // Initialize the I/O entry points in the firmware transfer vector. + // + debug(VRDBG_ENTRY, "VrIoInitialize BEGIN......\n"); + (PARC_CLOSE_ROUTINE) SYSTEM_BLOCK->FirmwareVector[CloseRoutine] = VrClose; + (PARC_MOUNT_ROUTINE) SYSTEM_BLOCK->FirmwareVector[MountRoutine] = VrMount; + (PARC_OPEN_ROUTINE) SYSTEM_BLOCK->FirmwareVector[OpenRoutine] = VrOpen; + (PARC_READ_ROUTINE) SYSTEM_BLOCK->FirmwareVector[ReadRoutine] = VrRead; + (PARC_SEEK_ROUTINE) SYSTEM_BLOCK->FirmwareVector[SeekRoutine] = VrSeek; + (PARC_WRITE_ROUTINE) SYSTEM_BLOCK->FirmwareVector[WriteRoutine] = VrWrite; + + (PARC_READ_STATUS_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[ReadStatusRoutine] = VrGetReadStatus; + + (PARC_GET_FILE_INFO_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[GetFileInformationRoutine] = + VrGetFileInformation; + (PARC_SET_FILE_INFO_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[SetFileInformationRoutine] = + VrSetFileInformation; + (PARC_GET_DIRECTORY_ENTRY_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[GetDirectoryEntryRoutine] = + VrGetDirectoryEntry; + + // + // Initialize the file table. + // + for (Index = 0; Index < FILE_TABLE_SIZE; Index++) { + FileTable[Index].Flags.Open = 0; + } + + debug(VRDBG_ENTRY, "VrIoInitialize ......END\n"); + return; +} + + +/* + * Name: GetFileTableEntry (internal) + * + * Description: + * This function looks for an unused entry in the FileTable. + * + * Arguments: + * Entry - Pointer to the variable that gets an index + * for the file table. + * + * Return Value: + * + * Returns ESUCCESS if a free entry is found + * or EMFILE if no entry is available. + * + */ +STATIC ARC_STATUS +GetFileTableEntry( + OUT PULONG Entry + ) +{ + ULONG Index; + + for (Index = 2; Index < FILE_TABLE_SIZE; Index++) { + if (FileTable[Index].Flags.Open == 0) { +#ifdef notdef + FileTable[Index].Position.LowPart = 0; + FileTable[Index].Position.HighPart = 0; +#endif // notdef + bzero((PCHAR)&FileTable[Index], sizeof(FILE_TABLE_ENTRY)); + *Entry = Index; + return ESUCCESS; + } + } + return EMFILE; +} + + +/* + * Name: GetDeviceAttribute (internal) + * + * Description: + * This function sets the specified File Table entry to the attribute. + * + * Arguments: + * FileId - Supplies the file table index. + * ConfNode - Supplies a pointer to the Configuration Node. + * + * Return Value: + * If the Configuration node is not peripheral, then return ENODEV. + * Otherwise, returns ESUCCESS. + * + */ +STATIC ARC_STATUS +GetDeviceAttribute( + IN ULONG FileId, + IN PCONFIGURATION_NODE ConfNode + ) +{ + if (ConfNode->Component.Class != PeripheralClass) { + warn("GetDeviceAttribute: node %s(%d) not PeripheralClass.\n", + ConfNode->ComponentName, ConfNode->Component.Key); + return ENODEV; + } + + if (ConfNode->Component.Type == MonitorPeripheral) { + FileTable[FileId].Flags.DisplayDevice = 1; + } + if (ConfNode->Component.Flags.Removable) { + FileTable[FileId].Flags.RemovableDevice = 1; + } + if (ConfNode->Component.Type == NetworkPeripheral) { + FileTable[FileId].Flags.NetworkDevice = 1; + } + if (ConfNode->Component.Flags.Input) { + FileTable[FileId].Flags.Read = 1; + } + if (ConfNode->Component.Flags.Output && + !(ConfNode->Component.Flags.ReadOnly)) { + FileTable[FileId].Flags.Write = 1; + } + + return ESUCCESS; +} + + +/* + * Name: AddLargeInt (internal) + * + * Description: + * This function adds a large integer into another large ingeger. + * + * Arguments: + * Position - Supplies a pointer to a variable to be added. + * Value - Supplies a pointer to a variable to add. + * + * Return Value: + * None. + * + */ +STATIC VOID +AddLargeInt( + PLARGE_INTEGER Position, + PLARGE_INTEGER Value + ) +{ + if ((Position->LowPart += Value->LowPart) < Value->LowPart) { + Position->HighPart++; + } + Position->HighPart += Value->HighPart; +} + + +/* + * Name: DecrementLarge (internal) + * + * Description: + * This function decrements a large integer. + * + * Arguments: + * Position - Supplies a pointer to a variable to be decremented. + * + * Return Value: + * None. + * + */ +STATIC VOID +DecrementLarge( + PLARGE_INTEGER Position + ) +{ + ULONG ULong = Position->LowPart; + + Position->LowPart--; + if (Position->LowPart > ULong) { + Position->HighPart--; + } +} + + +/* + * Name: MoveLargeInt (internal) + * + * Description: + * This function copies a large integer into another large ingeger. + * + * Arguments: + * Position - Supplies a pointer to a variable to be copied. + * Value - Supplies a pointer to a variable to copy. + * + * Return Value: + * None. + * + */ +STATIC VOID +MoveLargeInt( + PLARGE_INTEGER Position, + PLARGE_INTEGER Value + ) +{ + Position->LowPart = Value->LowPart; + Position->HighPart = Value->HighPart; +} + + +/* + * Name: IsLarge (internal) + * + * Description: + * This function determines whether a large integer contains zero. + * + * Arguments: + * Position - Supplies a pointer to a variable to be checked. + * + * Return Value: + * If the large integer is zero, then returns ZERO_LARGE. Otherwise, + * returns NOT_ZERO_LARGE. + * + */ +STATIC LONG +IsLarge( + PLARGE_INTEGER Position + ) +{ + if (Position->LowPart != 0) { + return NOT_ZERO_LARGE; + } + if (Position->HighPart != 0) { + return NOT_ZERO_LARGE; + } + return ZERO_LARGE; +} + |