📄 initdisk.c
字号:
}
void printCHS(char *title, struct CHS *chs)
{
/* has no fixed size for head/sect: is often 1/1 in our context */
printf("%s%4u-%u-%u", title, chs->Cylinder, chs->Head, chs->Sector);
}
/*
reason for this modules existence:
we have found a partition, and add them to the global
partition structure.
*/
/* Compute ceil(a/b) */
#define cdiv(a, b) (((a) + (b) - 1) / (b))
/* calculates FAT data:
code adapted by Bart Oldeman from mkdosfs from the Linux dosfstools:
Author: Dave Hudson
Updated by: Roman Hodek
Portions copyright 1992, 1993 Remy Card
and 1991 Linus Torvalds
*/
VOID CalculateFATData(ddt * pddt, ULONG NumSectors, UBYTE FileSystem)
{
UBYTE maxclustsize;
ULONG fatdata;
bpb *defbpb = &pddt->ddt_defbpb;
/* FAT related items */
defbpb->bpb_nfat = 2;
defbpb->bpb_ndirent = (FileSystem == FAT32
|| FileSystem == FAT32_LBA) ? 0 : 512;
/* normal value of number of entries in root dir */
defbpb->bpb_nreserved = (FileSystem == FAT32
|| FileSystem == FAT32_LBA) ? 0x20 : 1;
fatdata =
NumSectors - cdiv(defbpb->bpb_ndirent * DIRENT_SIZE,
defbpb->bpb_nbyte) - defbpb->bpb_nreserved;
maxclustsize = 128;
#ifdef DEBUG
if (FileSystem != FAT12)
DebugPrintf(("%ld sectors for FAT+data, starting with %d sectors/cluster\n", fatdata, defbpb->bpb_nsector));
#endif
switch (FileSystem)
{
case FAT12:
case FAT12_LBA:
{
unsigned fatdat, fatlength, clust, maxclust;
/* in DOS, FAT12 defaults to 4096kb (8 sector) - clusters. */
defbpb->bpb_nsector = 8;
/* Force maximal fatdata=32696 sectors since with our only possible sector
size (512 bytes) this is the maximum for 4k clusters.
#clus*secperclus+#fats*fatlength= 4077 * 8 + 2 * 12 = 32640.
max FAT12 size for FreeDOS = 16,728,064 bytes */
fatdat = (unsigned)fatdata;
if (fatdata > 32640)
fatdat = 32640;
/* The "+2*defbpb->bpb_nsector" is for the reserved first two FAT entries */
fatlength = cdiv(fatdat + 2 * defbpb->bpb_nsector,
defbpb->bpb_nbyte * 2 * defbpb->bpb_nsector / 3 +
defbpb->bpb_nfat);
/* Need to calculate number of clusters, since the unused parts of the
* FATS and data area together could make up space for an additional,
* not really present cluster. */
clust =
(fatdat - defbpb->bpb_nfat * fatlength) / defbpb->bpb_nsector;
maxclust = (fatlength * 2 * defbpb->bpb_nbyte) / 3;
if (maxclust > FAT12MAX)
maxclust = FAT12MAX;
DebugPrintf(("FAT12: #clu=%u, fatlength=%u, maxclu=%u, limit=%u\n",
clust, fatlength, maxclust, FAT12MAX));
if (clust > maxclust - 2)
{
clust = maxclust - 2;
DebugPrintf(("FAT12: too many clusters: setting to maxclu-2\n"));
}
defbpb->bpb_nfsect = fatlength;
memcpy(pddt->ddt_fstype, MSDOS_FAT12_SIGN, 8);
break;
}
case FAT16SMALL:
case FAT16LARGE:
case FAT16_LBA:
{
unsigned fatlength;
unsigned long clust, maxclust;
/* FAT16: start at 4 sectors per cluster */
defbpb->bpb_nsector = 4;
/* Force maximal fatdata=8387584 sectors (NumSectors=8387617)
since with our only possible sectorsize (512 bytes) this is the
maximum we can address with 64k clusters
#clus*secperclus+#fats*fatlength=65517 * 128 + 2 * 256=8386688.
max FAT16 size for FreeDOS = 4,293,984,256 bytes = 4GiB-983,040 */
if (fatdata > 8386688ul)
fatdata = 8386688ul;
do
{
DebugPrintf(("Trying with %d sectors/cluster:\n",
defbpb->bpb_nsector));
fatlength = (unsigned)cdiv(fatdata + 2 * defbpb->bpb_nsector,
(ULONG)defbpb->bpb_nbyte * defbpb->bpb_nsector / 2 +
defbpb->bpb_nfat);
/* Need to calculate number of clusters, since the unused parts of the
* FATS and data area together could make up space for an additional,
* not really present cluster. */
clust =
(fatdata - defbpb->bpb_nfat * fatlength) / defbpb->bpb_nsector;
maxclust = ((unsigned long)fatlength * defbpb->bpb_nbyte) / 2;
if (maxclust > FAT16MAX)
maxclust = FAT16MAX;
DebugPrintf(("FAT16: #clu=%lu, fatlen=%u, maxclu=%lu, limit=%u\n",
clust, fatlength, maxclust, FAT_MAGIC16));
if (clust > maxclust - 2)
{
DebugPrintf(("FAT16: too many clusters\n"));
clust = 0;
}
else if (clust <= FAT_MAGIC)
{
/* The <= 4086 avoids that the filesystem will be misdetected as having a
* 12 bit FAT. */
DebugPrintf(("FAT16: would be misdetected as FAT12\n"));
clust = 0;
}
if (clust)
break;
defbpb->bpb_nsector <<= 1;
}
while (defbpb->bpb_nsector && defbpb->bpb_nsector <= maxclustsize);
defbpb->bpb_nfsect = fatlength;
memcpy(pddt->ddt_fstype, MSDOS_FAT16_SIGN, 8);
break;
}
#ifdef WITHFAT32
case FAT32:
case FAT32_LBA:
{
unsigned long fatlength, clust, maxclust;
/* For FAT32, use the cluster size table described in the FAT spec:
* http://www.microsoft.com/hwdev/download/hardware/fatgen103.pdf
*/
unsigned sz_gb = (unsigned)(NumSectors / 2097152UL);
unsigned char nsector = 64; /* disks greater than 32 GB, 32K cluster */
if (sz_gb <= 32) /* disks up to 32 GB, 16K cluster */
nsector = 32;
if (sz_gb <= 16) /* disks up to 16 GB, 8K cluster */
nsector = 16;
if (sz_gb <= 8) /* disks up to 8 GB, 4K cluster */
nsector = 8;
if (NumSectors <= 532480UL) /* disks up to 260 MB, 0.5K cluster */
nsector = 1;
defbpb->bpb_nsector = nsector;
do
{
fatlength = cdiv(fatdata + 2 * defbpb->bpb_nsector,
(ULONG)defbpb->bpb_nbyte * defbpb->bpb_nsector / 4 +
defbpb->bpb_nfat);
/* Need to calculate number of clusters, since the unused parts of the
* FATS and data area together could make up space for an additional,
* not really present cluster. */
clust =
(fatdata - defbpb->bpb_nfat * fatlength) / defbpb->bpb_nsector;
maxclust = (fatlength * defbpb->bpb_nbyte) / 4;
if (maxclust > FAT32MAX)
maxclust = FAT32MAX;
DebugPrintf(("FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
clust, fatlength, maxclust, FAT32MAX));
if (clust > maxclust - 2)
{
clust = 0;
DebugPrintf(("FAT32: too many clusters\n"));
}
if (clust)
break;
defbpb->bpb_nsector <<= 1;
}
while (defbpb->bpb_nsector && defbpb->bpb_nsector <= maxclustsize);
defbpb->bpb_nfsect = 0;
defbpb->bpb_xnfsect = fatlength;
/* set up additional FAT32 fields */
defbpb->bpb_xflags = 0;
defbpb->bpb_xfsversion = 0;
defbpb->bpb_xrootclst = 2;
defbpb->bpb_xfsinfosec = 1;
defbpb->bpb_xbackupsec = 6;
memcpy(pddt->ddt_fstype, MSDOS_FAT32_SIGN, 8);
break;
}
#endif
}
pddt->ddt_fstype[8] = '\0';
}
STATIC void push_ddt(ddt *pddt)
{
ddt FAR *fddt = DynAlloc("ddt", 1, sizeof(ddt));
fmemcpy(fddt, pddt, sizeof(ddt));
if (pddt->ddt_logdriveno != 0) {
(fddt - 1)->ddt_next = fddt;
if (pddt->ddt_driveno == 0 && pddt->ddt_logdriveno == 1)
(fddt - 1)->ddt_descflags |= DF_CURLOG | DF_MULTLOG;
}
}
void DosDefinePartition(struct DriveParamS *driveParam,
ULONG StartSector, struct PartTableEntry *pEntry,
int extendedPartNo, int PrimaryNum)
{
ddt nddt;
ddt *pddt = &nddt;
struct CHS chs;
if (nUnits >= NDEV)
{
printf("more Partitions detected then possible, max = %d\n", NDEV);
return; /* we are done */
}
pddt->ddt_next = MK_FP(0, 0xffff);
pddt->ddt_driveno = driveParam->driveno;
pddt->ddt_logdriveno = nUnits;
pddt->ddt_descflags = driveParam->descflags;
/* Turn of LBA if not forced and the partition is within 1023 cyls and of the right type */
/* the FileSystem type was internally converted to LBA_xxxx if a non-LBA partition
above cylinder 1023 was found */
if (!InitKernelConfig.ForceLBA && !ExtLBAForce && !IsLBAPartition(pEntry->FileSystem))
pddt->ddt_descflags &= ~DF_LBA;
pddt->ddt_ncyl = driveParam->chs.Cylinder;
#ifdef DEBUG
if (pddt->ddt_descflags & DF_LBA)
DebugPrintf(("LBA enabled for drive %c:\n", 'A' + nUnits));
#endif
pddt->ddt_offset = StartSector;
pddt->ddt_defbpb.bpb_nbyte = SEC_SIZE;
pddt->ddt_defbpb.bpb_mdesc = 0xf8;
pddt->ddt_defbpb.bpb_nheads = driveParam->chs.Head;
pddt->ddt_defbpb.bpb_nsecs = driveParam->chs.Sector;
pddt->ddt_defbpb.bpb_nsize = 0;
pddt->ddt_defbpb.bpb_hidden = pEntry->RelSect;
if (pEntry->NumSect > 0xffff)
pddt->ddt_defbpb.bpb_huge = pEntry->NumSect;
else
pddt->ddt_defbpb.bpb_nsize = (UWORD) (pEntry->NumSect);
/* sectors per cluster, sectors per FAT etc. */
CalculateFATData(pddt, pEntry->NumSect, pEntry->FileSystem);
pddt->ddt_serialno = 0x12345678l;
/* drive inaccessible until bldbpb successful */
pddt->ddt_descflags |= init_readdasd(pddt->ddt_driveno) | DF_NOACCESS;
pddt->ddt_type = 5;
memcpy(&pddt->ddt_bpb, &pddt->ddt_defbpb, sizeof(bpb));
push_ddt(pddt);
/* Alain whishes to keep this in later versions, too
Tom likes this too, so he made it configurable by SYS CONFIG ...
*/
if (InitKernelConfig.InitDiskShowDriveAssignment)
{
char *ExtPri;
int num;
LBA_to_CHS(&chs, StartSector, driveParam);
ExtPri = "Pri";
num = PrimaryNum + 1;
if (extendedPartNo)
{
ExtPri = "Ext";
num = extendedPartNo;
}
printf("\r%c: HD%d, %s[%2d]", 'A' + nUnits,
(driveParam->driveno & 0x7f) + 1, ExtPri, num);
printCHS(", CHS= ", &chs);
printf(", start=%6lu MB, size=%6lu MB\n",
StartSector / 2048, pEntry->NumSect / 2048);
}
nUnits++;
}
/* Get the parameters of the hard disk */
STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam)
{
iregs regs;
struct _bios_LBA_disk_parameterS lba_bios_parameters;
ExtLBAForce = FALSE;
memset(driveParam, 0, sizeof *driveParam);
drive |= 0x80;
/* for tests - disable LBA support,
even if exists */
if (!InitKernelConfig.GlobalEnableLBAsupport)
{
goto StandardBios;
}
/* check for LBA support */
regs.b.x = 0x55aa;
regs.a.b.h = 0x41;
regs.d.b.l = drive;
init_call_intr(0x13, ®s);
if (regs.b.x != 0xaa55 || (regs.flags & 0x01))
{
goto StandardBios;
}
/* by ralph :
if DAP cannot be used, don't use
LBA
*/
if ((regs.c.x & 1) == 0)
{
goto StandardBios;
}
/* drive supports LBA addressing */
/* version 1.0, 2.0 have different verify */
if (regs.a.x < 0x2100)
LBA_WRITE_VERIFY = 0x4301;
memset(&lba_bios_parameters, 0, sizeof(lba_bios_parameters));
lba_bios_parameters.size = sizeof(lba_bios_parameters);
regs.si = FP_OFF(&lba_bios_parameters);
regs.ds = FP_SEG(&lba_bios_parameters);
regs.a.b.h = 0x48;
regs.d.b.l = drive;
init_call_intr(0x13, ®s);
/* error or DMA boundary errors not handled transparently */
if (regs.flags & 0x01)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -