⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 WINCE BOIS启动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		Sector   = 1;   

        gActivePartLBA = 0;

	#if 0
		printf("INFO: Floppy disk boot sector (C:H:S = 0x%x:0x%x:0x%x).\r\n\r\n", Cylinder, Head, Sector);
	#endif
	}
	
	//
	// User specify an offset to be applied to the boot sector data before writing? 
	//
	if (Offset)
	{
		// If we're writing to an offset within the boot sector, read the sector from disk
		// first to preserve the leading bytes.  Typically this is done to preserve the BIOS
		// Parameter Block (BPB) placed in the sector by the format utility.
		//
        if ((Status = ReadSector(DriveNum, Cylinder, Head, Sector, gTempSector)) != 0)
        {
            printf("ERROR: Unable to read boot sector (status=0x%x).\r\n", Status);
            return(-1);
        }
	}

	// Overlay the callers data.
	//
	memcpy((gTempSector + Offset), pSector, (SECTOR_SIZE - Offset));

    // Copy the BIOS parameter block for the caller.
    //
    memcpy(pBPB, (gTempSector + 3), sizeof(BIOSPB));

	// Write the boot sector data back to disk.
	//
    Status = WriteSector(DriveNum, Cylinder, Head, Sector, gTempSector);
    if (Status)
    {
        printf("ERROR: Unable to write boot sector (status=0x%x).\r\n", Status);
        return(-1);
    }

    return(0);
}

//
// Parse and validate user's arguments.
//
static int ParseArguments(int ArgC, char **ArgV, PPARAMS pUserParams)
{
	char DriveLetter;

	// Check for valid arguments.
	//
	if (ArgC < 4 && ArgC != 5)
		return(-1);

	if (!pUserParams)
		return(-1);

	memset(pUserParams, 0, sizeof(PARAMS));

	// "argv[0] -b offset sectfile bldrfile drive".

	// Get drive letter.
	//
	DriveLetter = TOLOWER(ArgV[ArgC - 1][0]);

	// Make sure user is passing a valid driver letter.
	//
	if (DriveLetter < 'a' || DriveLetter > 'z')
	{
		printf("ERROR: Invalid drive letter (%c:).\r\n", DriveLetter);
		return(-1);
	}
	if (DriveLetter < 'c')
	{
	    pUserParams->DriveNum = (FLOPPY_DISK_ID + (DriveLetter - 'a'));
	}
	else
	{
	    pUserParams->DriveNum = (FIXED_DISK_ID + (DriveLetter - 'c'));
	}
    pUserParams->DriveLetter = DriveLetter;

	// Get file name.
	//
	pUserParams->pSectorFileName = ArgV[ArgC - 3];	
	pUserParams->pLoaderFileName = ArgV[ArgC - 2];	

	// Check for optional byte offset
	//
	if (ArgC > 4)
	{
		if (!memicmp(ArgV[1], "-b:", 3))
		{
			pUserParams->Offset = (unsigned char)atoi(&ArgV[1][3]);		// Not a space since the above bounds check would have caught it.

			// Make sure offset value fits within a sector.
			//
			if (pUserParams->Offset >= SECTOR_SIZE)
			{
				printf("ERROR: Offset (0x%x)should be less than sector size (0x%x).\r\n", pUserParams->Offset, SECTOR_SIZE);
				return(-1);
			}
		}
	}

	return(0);
}


//
// Read a disk sector using the BIOS INT 13h command.
//
static int ReadSector(unsigned char Drive, unsigned short Cylinder, unsigned char Head, unsigned char Sector, unsigned char *pBuffer)
{
    int Status = 0;
	unsigned char Retries = 0;

	// If we're reading from a floppy, retry the operation a couple of times to allow for the floppy to spin up.
	//
	if (Drive < FIXED_DISK_ID)
		Retries = FLOPPY_IO_RETRIES;
	else
		Retries = FIXDISK_IO_RETRIES;

	do
	{
        _asm
        {
		    push   ax
		    push   bx
		    push   cx
		    push   dx
    
            mov    ah, 02h			; BIOS read sector command.
		    mov    al, 1			; Read 1 sector.
		    mov    dx, Cylinder     ; Cylinder number.
		    mov    cl, 06H
            shl    dh, cl
	        or     dh, Sector       ; Sector number.
            mov    cx, dx
            xchg   ch, cl
            mov    dl, Drive        ; Drive number.
            mov    dh, Head         ; Head number.
		    mov    bx, pBuffer		; Buffer address.
		    int	   13h
		    jnc    RS_Done
		    lea    bx, Status
		    mov	   [bx], ah        
RS_Done:
            pop    dx
		    pop    cx
		    pop    bx
		    pop    ax
        }
	}
	while(Status && Retries--);

    return(Status);
}


//
// Write a disk sector using the BIOS INT 13h command.
//
static int WriteSector(unsigned char Drive,  unsigned short Cylinder, unsigned char Head, unsigned char Sector, unsigned char *pBuffer)
{
    int Status = 0;
	unsigned char Retries = 0;

	// If we're writing to a floppy, retry the operation a couple of times to allow for the floppy to spin up.
	//
	if (Drive < FIXED_DISK_ID)
		Retries = FLOPPY_IO_RETRIES;
	else
		Retries = FIXDISK_IO_RETRIES;

	do
	{
        _asm
        {
		    push   ax
		    push   bx
		    push   cx
		    push   dx
    
            mov    ah, 03h			; BIOS write sector command.
		    mov    al, 1			; Read 1 sector.
		    mov    dx, Cylinder     ; Cylinder number.
		    mov    cl, 06H
            shl    dh, cl
	        or     dh, Sector       ; Sector number.
            mov    cx, dx
            xchg   ch, cl
            mov    dl, Drive        ; Drive number.
            mov    dh, Head         ; Head number.
		    mov    bx, pBuffer		; Buffer address.
		    int	   13h
		    jnc    WS_Done
		    lea    bx, Status
		    mov	   [bx], ah        
WS_Done:
		    pop    dx
		    pop    cx
		    pop    bx
		    pop    ax
        }
	}
	while(Status && Retries--);

    return(Status);
}


//
// Transfer the bootloader to the storage device and update the root directory.
//
static int TransferLoader(PPARAMS pParams, PBIOSPB pBPB)
{
    unsigned long RootDirLBA = 0;
    int Status = 0;
	unsigned short Cylinder;
    unsigned char Head, Sector;
    PDIRENTRY pDirEntry = NULL;
#define MAX_COMMAND_STRING	50
    unsigned char SystemCommand[MAX_COMMAND_STRING];

	//
    // This function transfers the bootloader image to the target drive.  The
    // loader image must be stored in a contiguous grouping of sectors and the
    // loader file name must be first in the FAT directory.  Both constraints
    // are required for the boot sector to locate and load the bootloader.
	//

    // Determine the active partitions root directory LBA and convert it to a physical CHS value
	// which is needed by the BIOS.
    //
    RootDirLBA = gActivePartLBA + (pBPB->NumFATs * pBPB->SectsPerFAT) + pBPB->RsvdSects;
    LBA2PCHS(RootDirLBA, &Cylinder, &Head, &Sector, pBPB);    

    // Read the first sector of the root directory.
    //
    if ((Status = ReadSector(pParams->DriveNum, Cylinder, Head, Sector, gTempSector)) != 0)
    {
        printf("ERROR: Unable to read a root directory sector (status=0x%x).\r\n", Status);
        return(-1);
    }

    // Update the first entry of the root directory so a later copy will use it.
    // MS-DOS's IO.SYS might be here if this is a formatted system disk.
    //
    pDirEntry = (PDIRENTRY)gTempSector;

#if 0
    printf("FileName: 0x%x %c%c%c%c%c%c%c.%c%c%c.\r\n", pDirEntry->FileName[0], pDirEntry->FileName[1], pDirEntry->FileName[2], pDirEntry->FileName[3], pDirEntry->FileName[4], pDirEntry->FileName[5], pDirEntry->FileName[6], pDirEntry->FileName[7], pDirEntry->FileExt[0], pDirEntry->FileExt[1], pDirEntry->FileExt[2]);
    printf("Attrib:   0x%x\r\n", pDirEntry->FATTr);
    printf("LModTime: 0x%x\r\n", pDirEntry->LModTime);
    printf("LModDate: 0x%x\r\n", pDirEntry->LModDate);
    printf("First Cluster: 0x%x\r\n", pDirEntry->FirstClust);
    printf("File Size: 0x%x\r\n", pDirEntry->FileSize);
#endif

	// Initialize first directory entry in order for copy to make use of it (it's typically updated by the DOS sys tool).
	//
    memset(pDirEntry->FileName, ' ', 8);
    memset(pDirEntry->FileName, ' ', 3);
    pDirEntry->FileName[0] = 0xe5;			// Deleted file tag.
    pDirEntry->FATTr       = 0;
    memset(pDirEntry->FOO, ' ', 10);
    pDirEntry->LModTime    = 0;
    pDirEntry->LModDate    = 0;
    pDirEntry->FirstClust  = 0;
    pDirEntry->FileSize    = 0;
   
    // Write the updated boot sector back to disk.
    // 
    if ((Status = WriteSector(pParams->DriveNum, Cylinder, Head, Sector, gTempSector)) != 0)
    {
        printf("ERROR: Unable to write root a directory sector (status=0x%x).\r\n", Status);
        return(-1);
    }

    // Copy the bootloader image.  It's assumed that the copy will be to a
    // contiguous group of sectors.  This might not be true if the disk
    // already contains files (documented setup requirement) or if the disk
    // contains bad sector(s).
    //
    // TODO - this area should be revisited.
    //
    sprintf(SystemCommand, "copy %s %c:", pParams->pLoaderFileName, pParams->DriveLetter);
    SystemCommand[MAX_COMMAND_STRING - 1] = '\0';

    if (system(SystemCommand) == -1)
    {
        printf("ERROR: Unable to transfer bootloader.\r\n");
        return(-1);
    }

    return(0);
}


//
// Convert a LBA address to a physical CHS address that's used by the BIOS.
//
static void LBA2PCHS(unsigned long LBA, unsigned short *pCylinder, unsigned char  *pHead, unsigned char  *pSector, PBIOSPB pBPB)
{
    unsigned short Temp = 0;

    // Do the math...
    *pCylinder = (unsigned short)(LBA / (pBPB->NumHeads * pBPB->SectsPerTrack));
    Temp       = (unsigned short)(LBA % (pBPB->NumHeads * pBPB->SectsPerTrack));
    *pHead     = (unsigned char)(Temp / pBPB->SectsPerTrack);
    *pSector   = (unsigned char)(Temp % pBPB->SectsPerTrack) + 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -