/************************************************************************/ /* Linux partition filter. */ /* (C) Copyright Deon van der Westhuysen, July 1995. */ /* */ /* Dedicated to Jesus Christ, my Lord and Saviour. */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2, or (at your option) */ /* any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /* This code is still under development; expect some rough edges. */ /* */ /************************************************************************/ #include "debug.h" #include "e2data.h" #include "e2router.h" #include "e2wrap.h" #include "e2inutil.h" #include "e2init.h" USHORT StartInitData= 0; /* Use addr as pointer to start of init data */ /* Initialization function for the driver. Only called once. */ void E2Init (PRPINITOUT Req) { int UnitCount; char FAR *pCmdLine; /* Initialize some of the important global variables. */ DevHelp= ((PRPINITIN) Req)->DevHlpEP; /* Get pointer to DevHelp */ pDataSeg= (PVOID) &pDataSeg; /* Get pointer to data seg */ OFFSETOF(pDataSeg)= 0; VirtToPhys (pDataSeg,&ppDataSeg); /* Get the physical address */ /* of the data segment */ for (MountCount= 0; MountCountInitArgs; /* Get command line args */ OFFSETOF(pCmdLine)=(USHORT) ((PDDD_PARM_LIST) pCmdLine)->cmd_line_args; ProcessCmdline (pCmdLine); InitPrint ("Linux partition filter. Copyright 1995, Deon van der Westhuysen." " v1.2b\n\r" "Development version (Beta).\n\r"); InitScanDrivers(); /* Scan for partitions... */ InitGetUnitFS(); /* Determine FS for each unit */ InitSortUnits(); /* Sort the units */ if (MountCount>NumVirtUnits) MountCount =NumVirtUnits; /* Get correct number of */ /* units to be mounted. */ /* Check that each entry points to a valid unit. If not valid, point to */ /* first unit. (Which can only be allocated once, thus one drive letter.) */ for (UnitCount=0;UnitCount=NumVirtUnits) MountTable[UnitCount]= 0; if (!NumVirtUnits) { InitPrint ("No Linux partitions were found: filter not installed."); Req->Unit= 0; Req->CodeEnd= 0; /* No code to keep */ Req->DataEnd= 0; /* No data to keep */ Req->rph.Status= STDON+STERR+ERROR_I24_QUIET_INIT_FAIL; /* Indicate failure */ return; } ADDHandle= RegisterADD (E2FilterIORBWrapper,FILTER_ADD_NAME); /* Register filter */ if (!ADDHandle) /* Check registration */ { InitPrint ("Could't register filter. Installation aborted."); while (NumBaseUnits) InitRemoveBaseUnit(); /* Free all base units */ Req->Unit= 0; Req->CodeEnd= 0; /* No code to keep */ Req->DataEnd= 0; /* No data to keep */ Req->rph.Status= STDON+STERR+ERROR_I24_QUIET_INIT_FAIL; /* Indicate failure */ return; } for (UnitCount= 0; UnitCountUnit= 0; Req->CodeEnd= ((USHORT)E2Init); /* Pointer to end of code */ Req->DataEnd= ((USHORT)&StartInitData); /* Pointer to end of data */ Req->rph.Status= STDON; /* Everything is OK */ } /* Scan the system for installed device drivers. Scan the drivers for */ /* adapters in turn. */ void InitScanDrivers (void) { PADDEntryPoint pADDEntry; /* .ADD entry point adapter */ PDevClassTableStruc pDCTable; /* Pointer to list of ADDs */ PDevClassTableEntry pDCEntry; /* Pointer to device entry */ int DeviceCount; pDCTable= E2GetADDTable(); InitPrintVerbose ("Scanning Adapter device drivers:"); for (DeviceCount= pDCTable->DCCount,pDCEntry= pDCTable->DCTableEntries; DeviceCount--; pDCEntry++) { InitPrintVerbose (pDCEntry->DCName); pADDEntry = (PVOID) MAKEP(pDCEntry->DCSelector,pDCEntry->DCOffset); InitScanAdapter (pADDEntry); } } /* This function scans a driver for all the adapters it controls. */ void InitScanAdapter (PADDEntryPoint pADDEntry) { static UCHAR DeviceTable[MAX_DEVTABLE_SIZE]; /* Holds info about adapters */ PADAPTERINFO pAdapterInfo; /* Pointer to adapter info */ int NumAdapters; int AdapterCount; if (InitReadDevTable(pADDEntry,(PDEVICETABLE) &DeviceTable, sizeof(DeviceTable))) /* Get list of adapters */ { InitPrintVerbose ("Error reading the device table... skipping device."); return; } NumAdapters= ((PDEVICETABLE)&DeviceTable)->TotalAdapters; for (AdapterCount= 0;AdapterCount< NumAdapters;AdapterCount++) { pAdapterInfo= ((PDEVICETABLE) &DeviceTable)->pAdapter[AdapterCount]; InitPrintVerbose ("Scanning adapter..."); if (pAdapterInfo->AdapterFlags&AF_ASSOCIATED_DEVBUS) InitPrintVerbose ("Skipping associated device bus of the adapter."); else InitScanUnits (pADDEntry,pAdapterInfo); } } /* This function scans an adapter for all the units it controls. */ void InitScanUnits (PADDEntryPoint pADDEntry, PADAPTERINFO pAdapterInfo) { PUNITINFO pUnitInfo; /* Information about unit */ USHORT UnitFlags; /* Flags for current unit */ USHORT UnitType; /* Type flag for units */ USHORT FilterHandle; /* Handle of unit filter */ PADDEntryPoint pUnitADDEntry; /* Entry point for unit */ NPBaseUnitRec pBaseUnit; /* Pointer to base unit rec */ int NumUnits; /* Num units on adapter */ int UnitCount; NumUnits= pAdapterInfo->AdapterUnits; pUnitInfo= pAdapterInfo->UnitInfo; /* Modify some fields in adapter info for later use by base units. */ memcpy (pAdapterInfo->AdapterName,FILTER_ADD_NAME,sizeof(FILTER_ADD_NAME)); pAdapterInfo->AdapterUnits= 1; pAdapterInfo->AdapterFlags&=~(AF_IBM_SCB|AF_CHS_ADDRESSING); for (UnitCount= 0;UnitCountUnitInfo+UnitCount,sizeof(UNITINFO)); /* Copy UnitInfo into first */ /* slot in the array */ UnitFlags= pUnitInfo->UnitFlags; UnitType= pUnitInfo->UnitType; FilterHandle= pUnitInfo->FilterADDHandle; if (FilterHandle) pUnitADDEntry= InitGetDriverEP (FilterHandle); else pUnitADDEntry= pADDEntry; if (UnitType!=UIB_TYPE_DISK) { InitPrintVerbose ("Unit is not a disk, skipping."); continue; } if (UnitFlags&UF_REMOVABLE) { InitPrintVerbose ("Unit is removable (=not partitioned), skipping."); continue; } if (UnitFlags&(UF_NODASD_SUPT|UF_DEFECTIVE)) { InitPrintVerbose ("Unit defective or no OS2DASD.DMD support, skipping."); continue; } if (!InitAddBaseUnit(pUnitADDEntry,pAdapterInfo)) if (!InitScanPartitions(pUnitADDEntry)) /* If no partitions found: */ InitRemoveBaseUnit(); /* Free base unit again */ } } /* Return the entry point for a driver given its handle */ PADDEntryPoint InitGetDriverEP (USHORT FilterHandle) { PDevClassTableStruc pDCTable; /* Pointer to list of ADDs */ PDevClassTableEntry pDCEntry; /* Pointer to device entry points */ pDCTable= E2GetADDTable(); /* Get device class list */ pDCEntry= pDCTable->DCTableEntries+FilterHandle-1; /* Point to entry for ADDHandle */ return (PVOID) MAKEP(pDCEntry->DCSelector,pDCEntry->DCOffset); /* Return the entry point */ } /* Scan for partitions on a given unit. */ USHORT InitScanPartitions (PADDEntryPoint pAddEP) { static MBR BootRecord= {0}; NPBaseUnitRec pBaseUnit; USHORT UnitHandle; USHORT Result; int FoundExt; int NumAdded; int Count; PARTITIONENTRY *pPartInfo; ULONG PartRBA= 0; ULONG ExtPartRBA= 0; pBaseUnit= BaseUnits+NumBaseUnits-1; UnitHandle= pBaseUnit->UnitHandle; NumAdded= 0; /* Number partitions added */ /* to partition list */ InitPrintVerbose ("Reading master boot record."); do { FoundExt= 0; if (InitReadSector (pAddEP,UnitHandle,PartRBA, ppDataSeg+((USHORT)&BootRecord))) { /* If error reading sector */ InitPrint ("Read failure... :-("); break; /* Done with this unit */ } if (BootRecord.Signature!=0xAA55) /* Test MBR signature */ { InitPrint ("Invalid signature in partition table."); break; /* Done with this unit */ } pPartInfo= BootRecord.PartitionTable; /* Ptr to partition entry */ for (Count=0;Count<4;Count++) /* Scan for linux partitions... */ if (InitIsVirtType(pPartInfo[Count].SysIndicator)) { InitPrintVerbose ("Found a partition to virtualize."); NumAdded+= InitAddVirtualUnit (PartRBA+pPartInfo[Count].RelativeSectors, pPartInfo[Count].NumSectors, pPartInfo[Count].SysIndicator); } for (Count=0;Count<4;Count++) /* Scan for extended partitions... */ if (pPartInfo[Count].SysIndicator==PARTITION_EXTENDED) { InitPrintVerbose ("Found an extended partition."); FoundExt= 1; PartRBA= ExtPartRBA+ pPartInfo[Count].RelativeSectors; if (!ExtPartRBA) ExtPartRBA= PartRBA; } } while (FoundExt); return NumAdded; } /* Return 1 if the partition should be virtualized; else returns 0. */ int InitIsVirtType(UCHAR PartType) { if ((PartType==PARTITION_LINUX)|| (PartType==(PARTITION_LINUX|PARTITION_HIDDEN))) return 1; if (!(InstallFlags&FI_ALLPART)) return 0; switch (PartType) { case PARTITION_DOSSMALL: case PARTITION_DOSMED: case PARTITION_DOSLARGE: case PARTITION_IFS: case PARTITION_DOSSMALL | PARTITION_HIDDEN: case PARTITION_DOSMED | PARTITION_HIDDEN: case PARTITION_DOSLARGE | PARTITION_HIDDEN: case PARTITION_IFS | PARTITION_HIDDEN: return 1; default: return 0; } } /* Function to scan the command line and set global variables based on */ /* options specified in the command line. */ void ProcessCmdline (char FAR *pCmdLine) { int TempInt; char TempChar; /* InstallFlags= 0 on entry... */ while (*pCmdLine) { if (*(pCmdLine++)!='/') /* Scan for a '/' on cmdline */ continue; switch (*(pCmdLine++)) { case 'm': case 'M': MountCount= 0; /* Assume nothing to mount */ while (1) /* Loop to read numbers */ { while ((*pCmdLine==' ')||(*pCmdLine=='\t')) pCmdLine++; /* Skip any spaces */ if (!*pCmdLine) break; /* Exit if end-of-line */ /* Read a number here... */ TempChar= *pCmdLine; TempInt= 0; while ((TempChar>='0')&&(TempChar<='9')) { TempInt= TempInt*10+TempChar-'0'; TempChar= *(++pCmdLine); } MountTable[MountCount++]= TempInt; while ((*pCmdLine==' ')||(*pCmdLine=='\t')) pCmdLine++; /* Skip any spaces */ if (!*pCmdLine) return; /* Exit if end-of-line */ if (*pCmdLine!=',') break; /* Stop if no next number */ pCmdLine++; } break; case 'q': case 'Q': InstallFlags |= FI_QUIET; break; case 'v': case 'V': InstallFlags |= FI_VERBOSE; break; case 'a': case 'A': InstallFlags |= FI_ALLPART; break; case 'w': case 'W': InstallFlags |= FI_ALLOWWRITE; break; default: InitPrintVerbose ("Unknown command line option encountered"); break; } } } void InitGetUnitFS (void) { static UCHAR SectorBuf[SECTOR_SIZE]= {0}; int Count; NPVirtUnitRec pUnitRec; NPBaseUnitRec pSourceRec; for (Count= 0;CountpSourceUnitRec; if (InitReadSector (pSourceRec->pADDEntry,pSourceRec->UnitHandle, pUnitRec->StartRBA,ppDataSeg+((USHORT)&SectorBuf))) /* Error- shouldn't happen */ pUnitRec->Hdr.Flags|=F_ALLOCATED; /* Allocate so that no one */ /* else can use this unit */ else pUnitRec->HiddenSectors=*((ULONG *)(SectorBuf+0x1C)); /* Save num of hidden sectors */ switch ((pUnitRec->PartSysIndicator)&~PARTITION_HIDDEN) { case PARTITION_DOSSMALL: case PARTITION_DOSMED: case PARTITION_DOSLARGE: pUnitRec->FSType=FS_DOSFAT; /* Assume this partitions of */ /* this type will always be */ /* FAT partitions. */ default: pUnitRec->FSType=FS_UNKNOWN; break; } } } void InitSortUnits (void) { } void InitPrint (char FAR *Message) { if (!(InstallFlags&FI_QUIET)) E2Print (Message); } void InitPrintVerbose (char FAR *Message) { if (InstallFlags&FI_VERBOSE) InitPrint (Message); }