mirror of
https://github.com/WindowsNT351/CE-Collections.git
synced 2025-12-27 01:20:25 +08:00
977 lines
26 KiB
C
977 lines
26 KiB
C
/*++
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
Copyright (c) 1995-1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
Functions:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include <conio.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "loadcepc.h"
|
|
#include "xmsapi.h"
|
|
#include "ethernet.h"
|
|
#include "..\inc\bootarg.h"
|
|
|
|
#pragma warning(disable: 4001)
|
|
|
|
#define CHUNKSIZE 32768
|
|
#define COPY_FLAG_UPDATE_EXISTING 0x0001
|
|
#define COPY_FLAG_UPDATE_OR_ADD 0x0002
|
|
|
|
int LoadImage(BOOL bVerbose, BOOL bParallelDownload, char *pszFileName, PULONG pulEntryAddress);
|
|
|
|
int ExecuteImage(BOOL bVerbose, ULONG ulEntryPoint);
|
|
|
|
void Launch(ULONG ulEntryPoint, ULONG ulArguments);
|
|
|
|
UCHAR SetVideoMode(UCHAR iDesiredMode);
|
|
|
|
UCHAR GetPCIConfigMechanism();
|
|
BOOL ParseEthernetOptions(char * argstr);
|
|
|
|
extern int NoPPFS; // parallel port not present flag
|
|
int OEMParallelPortGetByte(void);
|
|
void OEMParallelPortSendByte(UCHAR chData);
|
|
void OEMParallelPortInit(void);
|
|
void DisplayDirectory(char *pszPath);
|
|
void GetFile(char *pszSource, char *pszDestination, USHORT usCopyFlags);
|
|
|
|
BOOL SMCDetect(BYTE **ppbBaseAddress, USHORT *pwIrq);
|
|
|
|
const unsigned char BootHeader[] = {
|
|
0xAA, // header = 4 bytes
|
|
0x55,
|
|
0x55,
|
|
0xAA,
|
|
0x00, // opcode = 2 bytes (0 = BOOT)
|
|
0x00,
|
|
};
|
|
#define BOOT_HEADER_SIZE (sizeof(BootHeader) / sizeof(BootHeader[0]))
|
|
|
|
const unsigned char BootTail[] = {
|
|
0x5A, // trail = 4 bytes
|
|
0xA5,
|
|
0x0A,
|
|
0x1A
|
|
};
|
|
#define BOOT_TAIL_SIZE (sizeof(BootTail) / sizeof(BootTail[0]))
|
|
|
|
#define BOOT_TYPE -4 // boot type for x86
|
|
|
|
struct
|
|
{
|
|
ULONG ulRate;
|
|
UCHAR ucDivisor;
|
|
} BaudTable[] =
|
|
{
|
|
{ 9600, 12 },
|
|
{ 19200, 6 },
|
|
{ 38400, 3 },
|
|
{ 57600, 2 },
|
|
{ 115200, 1 }
|
|
};
|
|
|
|
#define NUM_BAUD_RATES (sizeof(BaudTable) / sizeof(BaudTable[0]))
|
|
|
|
BOOT_ARGS BootArgs;
|
|
|
|
BOOL bSerialDownload=FALSE;
|
|
extern int OEMReadDebugByte(void);
|
|
extern void OEMReadDebugBytes(unsigned char * ucBuffer, int usReadSize);
|
|
extern void OEMWriteDebugByte(unsigned char ch);
|
|
|
|
void
|
|
usage(char *pszProgramNameArg)
|
|
{
|
|
char * pszProgram;
|
|
|
|
pszProgram = strrchr(pszProgramNameArg, '\\');
|
|
|
|
if (pszProgram != NULL)
|
|
{
|
|
pszProgram++;
|
|
}
|
|
else
|
|
{
|
|
pszProgram = pszProgramNameArg;
|
|
}
|
|
|
|
printf(
|
|
"%s: Loads an NK ROM image into memory and boots it\n\n"
|
|
"Usage:%s [/B:baud] [/C:port] [/D:display] [/E:Card:IO:IRQ] [/P] [/Q]\n"
|
|
"\t\t[/H] [/V] [<file name>]\n\n"
|
|
"\t/B\tBaudrate - 9600, 19200, 38400, 57600, or 115200 (default 19200)\n"
|
|
"\t/C\tCOM Port - 1 = COM1, 2 = COM2 (default COM1)\n"
|
|
"\t/D\tDisplay Resolution - 0 = 320x200 (default), 1 = 480x240x256,\n"
|
|
"\t\t\t2 = 640x480x256, 3 = 800x600x256, 4 = 1024x768x256\n"
|
|
"\t\t\t5 = 240x320x256 \n"
|
|
"\t/P\tParallel port boot download.\n"
|
|
"\t/Q\tSerial port boot download.\n"
|
|
"\t/E:Card:IO:IRQ\tCard 0 = SMC9000, 1 = NE2000 (For Debug Ethernet)\n"
|
|
"\t\t\t(Other debug ethernet options in hex digits)\n"
|
|
"\t/H\tHelp - displays this message\n"
|
|
"\t/V\tVerbose - displays extra status information during boot\n"
|
|
"\n\tDefault <file name> is NK.BIN except for /P option which uses\n"
|
|
"\tdefault on host unless <file name> specified.\n"
|
|
"\nPress any key for more options...\n",
|
|
pszProgram, pszProgram);
|
|
__asm
|
|
{
|
|
push dx
|
|
xor ax,ax
|
|
int 0x16
|
|
pop dx
|
|
}
|
|
printf(
|
|
"usage: %s -s[:]<pattern> -(g|r|u)[[:]<pattern> [<destination>]\n"
|
|
"-s Show a directory of files matching <pattern>.\n\n"
|
|
"-g Get files matching <pattern> and copy them to the\n"
|
|
" optionally specified <destination>. Any existing file with\n"
|
|
" the same name will be overwritten.\n\n"
|
|
"-r Refresh files matching <pattern> which already exist in <destination>\n"
|
|
" and have a timestamp newer than the one in <destination>.\n\n"
|
|
"-u Update files matching <pattern> which don't already exist in\n"
|
|
" <destination> or those that have a timestamp newer than those\n"
|
|
" in <destination>.\n\n"
|
|
"<pattern> Windows filename path with optional wildcard characters.\n\n"
|
|
"<destination> If not specified then the current directory is the\n"
|
|
" default.\n"
|
|
" If specified and it doesn't exist and the last character is \\,\n"
|
|
" then the directory is created. Otherwise <destination> is\n"
|
|
" treated as the name of the file.\n"
|
|
" It is an error for <pattern> to match multiple files\n"
|
|
" when <destination> specifies a file.\n",
|
|
pszProgram);
|
|
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
|
|
char * pszFileName = "nk.bin";
|
|
ULONG ulEntryPoint;
|
|
ULONG ulArguments;
|
|
int xmsError;
|
|
BOOL bEnabled;
|
|
BOOL bVerbose = FALSE;
|
|
BOOL bParallelDownload=FALSE;
|
|
int iDesiredMode = 0;
|
|
ULONG ulBaudRate;
|
|
char cOption;
|
|
int i;
|
|
int iPpfstool=0;
|
|
|
|
|
|
/* Set up boot args struct */
|
|
BootArgs.ucVideoMode = 0;
|
|
BootArgs.ucComPort = 1;
|
|
BootArgs.ucBaudDivisor = 6;
|
|
BootArgs.ucPCIConfigType = 0;
|
|
|
|
BootArgs.dwSig = BOOTARG_SIG;
|
|
BootArgs.dwLen = sizeof(BOOT_ARGS);
|
|
|
|
OEMParallelPortInit(); // initialize parallel port
|
|
/*
|
|
** Parse arguments
|
|
*/
|
|
|
|
if (argc > 1)
|
|
{
|
|
int iArgIndex;
|
|
|
|
for (iArgIndex = 1; iArgIndex < argc; iArgIndex++)
|
|
{
|
|
if (argv[iArgIndex][0] != '/' && argv[iArgIndex][0] != '-')
|
|
{
|
|
break;
|
|
}
|
|
cOption=tolower(argv[iArgIndex][1]);
|
|
switch (argv[iArgIndex][1])
|
|
{
|
|
case 'b': /* Baud rate */
|
|
case 'B':
|
|
if (argv[iArgIndex][2] != ':' ||
|
|
argv[iArgIndex][3] < '0' || argv[iArgIndex][3] > '9')
|
|
{
|
|
printf("Invalid option - %s\n", argv[iArgIndex]);
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
ulBaudRate = atol(&argv[iArgIndex][3]);
|
|
|
|
for (i = 0; i < NUM_BAUD_RATES; i++)
|
|
{
|
|
if (BaudTable[i].ulRate == ulBaudRate)
|
|
{
|
|
BootArgs.ucBaudDivisor = BaudTable[i].ucDivisor;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= NUM_BAUD_RATES)
|
|
{
|
|
printf("Unsupported baud rate - %s\n", argv[iArgIndex]);
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case 'c': /* COM port */
|
|
case 'C':
|
|
if (argv[iArgIndex][2] != ':' ||
|
|
(argv[iArgIndex][3] != '1' && argv[iArgIndex][3] != '2' &&
|
|
argv[iArgIndex][3] != '3' && argv[iArgIndex][3] != '4'))
|
|
{
|
|
printf("Invalid option - %s\n", argv[iArgIndex]);
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
BootArgs.ucComPort = (UCHAR)(argv[iArgIndex][3] - '0');
|
|
break;
|
|
|
|
case 'd': /* Display mode */
|
|
case 'D':
|
|
if (argv[iArgIndex][2] != ':' ||
|
|
argv[iArgIndex][3] < '0' || argv[iArgIndex][3] > '5')
|
|
{
|
|
printf("Invalid option - %s\n", argv[iArgIndex]);
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
iDesiredMode = argv[iArgIndex][3] - '0';
|
|
break;
|
|
|
|
case 'p': /* Parallel port boot download */
|
|
case 'P':
|
|
bParallelDownload=TRUE;
|
|
pszFileName= NULL;
|
|
break;
|
|
|
|
case 'q': /* Serial port boot download */
|
|
case 'Q':
|
|
bSerialDownload=TRUE;
|
|
pszFileName= NULL;
|
|
break;
|
|
|
|
case 'v':
|
|
case 'V':
|
|
bVerbose = TRUE;
|
|
break;
|
|
|
|
case 'S':
|
|
case 's':
|
|
{
|
|
char *pszPath;
|
|
iPpfstool=1;
|
|
if (argv[iArgIndex][2] != '\0')
|
|
{
|
|
pszPath = &argv[iArgIndex][2];
|
|
if (*pszPath == ':')
|
|
{
|
|
pszPath++;
|
|
}
|
|
}
|
|
else if (argc > (i+1) && argv[iArgIndex+1][0] != '-' && argv[iArgIndex+1][0] != '/')
|
|
{
|
|
pszPath = argv[iArgIndex+1];
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
pszPath = "*.*";
|
|
}
|
|
DisplayDirectory(pszPath);
|
|
}
|
|
break;
|
|
|
|
case 'E':
|
|
case 'e':
|
|
if (!ParseEthernetOptions(argv[iArgIndex])) {
|
|
printf("Invalid option - %s\n", argv[iArgIndex]);
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case 'G':
|
|
case 'R':
|
|
case 'U':
|
|
case 'g':
|
|
case 'r':
|
|
case 'u':
|
|
{
|
|
char *pszSource;
|
|
char *pszDestination;
|
|
|
|
iPpfstool=1;
|
|
if (argv[iArgIndex][2] != '\0')
|
|
{
|
|
pszSource = &argv[iArgIndex][2];
|
|
if (*pszSource == ':')
|
|
{
|
|
pszSource++;
|
|
}
|
|
}
|
|
else if (argc > (iArgIndex+1) && argv[iArgIndex+1][0] != '-' && argv[iArgIndex+1][0] != '/')
|
|
{
|
|
pszSource = argv[iArgIndex+1];
|
|
iArgIndex++;
|
|
}
|
|
else
|
|
{
|
|
printf("Error source path missing\n");
|
|
break;
|
|
}
|
|
|
|
if (argc > (iArgIndex+1) && argv[iArgIndex+1][0] != '-' && argv[iArgIndex+1][0] != '/')
|
|
{
|
|
pszDestination = argv[iArgIndex+1];
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
pszDestination = NULL;
|
|
}
|
|
|
|
GetFile(
|
|
pszSource, pszDestination,
|
|
cOption == 'r' ? COPY_FLAG_UPDATE_EXISTING :
|
|
cOption == 'u' ? COPY_FLAG_UPDATE_OR_ADD :
|
|
0);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
printf("Unrecognized option - %s\n", argv[iArgIndex]);
|
|
/* FALL THROUGH */
|
|
|
|
case '?':
|
|
case 'h':
|
|
case 'H':
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (iArgIndex == (argc - 1))
|
|
{
|
|
pszFileName = argv[iArgIndex];
|
|
}
|
|
}
|
|
|
|
if (iPpfstool)
|
|
return 0;
|
|
|
|
if (!XmsIsInstalled())
|
|
{
|
|
printf("HIMEM.SYS must be loaded\n");
|
|
return 2;
|
|
}
|
|
|
|
if (bVerbose)
|
|
{
|
|
if ((xmsError = XmsQueryA20(&bEnabled)) != XMS_SUCCESS)
|
|
{
|
|
printf("Error querying A20 status - %s\n", XmsErrorString(xmsError));
|
|
|
|
return 3;
|
|
}
|
|
|
|
if (bEnabled)
|
|
{
|
|
printf("Warning A20 line already enabled\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Check if PCI Bios is available, if so find out config mechanism
|
|
*/
|
|
|
|
BootArgs.ucPCIConfigType = GetPCIConfigMechanism();
|
|
|
|
if (!LoadImage(bVerbose, bParallelDownload, pszFileName, &ulEntryPoint))
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
/*
|
|
** Enable A20 line
|
|
*/
|
|
|
|
if ((xmsError = XmsLocalEnableA20()) != XMS_SUCCESS)
|
|
{
|
|
printf("Can't enable A20 line, error = 0x%4.4X\n", xmsError);
|
|
|
|
return 5;
|
|
}
|
|
|
|
BootArgs.ucVideoMode = SetVideoMode(iDesiredMode);
|
|
|
|
if (bSerialDownload)
|
|
BootArgs.ucBaudDivisor|=0x80;
|
|
|
|
if (bVerbose)
|
|
{
|
|
printf("Jumping to 0x%8.8lX\n", ulEntryPoint);
|
|
}
|
|
|
|
/*
|
|
** Convert arguments to linear addres
|
|
*/
|
|
|
|
ulArguments = (((ULONG)(void far *)&BootArgs) >> 16) << 4;
|
|
ulArguments += ((ULONG)(void far *)&BootArgs) & 0xFFFF;
|
|
|
|
Launch(ulEntryPoint, ulArguments);
|
|
|
|
/*
|
|
** Launch shouldn't have returned
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
USHORT DownloadRead(int hImage, UCHAR* ucBuffer, USHORT usReadSize, BOOL bParallelDownload) {
|
|
int loop, loop2;
|
|
|
|
if (bParallelDownload) {
|
|
for (loop = 0; loop < usReadSize; loop++ ) {
|
|
ucBuffer[loop]= (UCHAR)OEMParallelPortGetByte();
|
|
if (NoPPFS)
|
|
return 0;
|
|
}
|
|
return usReadSize;
|
|
} else if (bSerialDownload) {
|
|
OEMReadDebugBytes(ucBuffer,usReadSize);
|
|
return usReadSize;
|
|
} else
|
|
return _read(hImage, ucBuffer, usReadSize);
|
|
}
|
|
|
|
int
|
|
LoadImage(BOOL bVerbose, BOOL bParallelDownload, char *pszFileName, PULONG pulEntryPoint)
|
|
{
|
|
int hImage;
|
|
long lImageSize;
|
|
|
|
int xmsError;
|
|
|
|
USHORT usTotalFree;
|
|
USHORT usLargestBlock;
|
|
USHORT usBlockHandle;
|
|
|
|
ULONG ulLinearAddress;
|
|
|
|
ULONG ulSectionAddress;
|
|
ULONG ulSectionSize;
|
|
ULONG ulSectionChecksum;
|
|
|
|
ULONG ulSectionOffset;
|
|
ULONG ulChecksum;
|
|
|
|
USHORT usReadSize;
|
|
USHORT usAmountRead;
|
|
ULONG ulReadTotal=0;
|
|
ULONG ulReadProgress=0;
|
|
|
|
USHORT usIndex;
|
|
|
|
static UCHAR ucBuffer[ CHUNKSIZE ];
|
|
|
|
static UCHAR ucSignature[] = { 'B', '0', '0', '0', 'F', 'F', '\n' };
|
|
int i;
|
|
UCHAR BootPacket[256];
|
|
UCHAR *pDestByte;
|
|
UCHAR *pTemp;
|
|
unsigned int chksum;
|
|
long int uiTemp;
|
|
long int bootType;
|
|
unsigned len;
|
|
|
|
/*
|
|
** Stop the floppy motor in case it contained the image file
|
|
*/
|
|
|
|
__asm
|
|
{
|
|
push dx
|
|
mov dx, 03F2h ; Floppy motor and DMA control
|
|
in al, dx
|
|
and al, 00Fh ; Clear motor on bits
|
|
out dx, al
|
|
pop dx
|
|
}
|
|
/*
|
|
** Find the largest Extended Memory block and allocate it
|
|
*/
|
|
|
|
xmsError = XmsQueryFreeExtendedMemory(&usLargestBlock, &usTotalFree);
|
|
|
|
if (xmsError != XMS_SUCCESS)
|
|
{
|
|
printf("Error querying free extended memory - %s\n", XmsErrorString(xmsError));
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (bVerbose)
|
|
{
|
|
/*
|
|
** Print info about memory available
|
|
*/
|
|
|
|
printf(
|
|
"Total free extended memory = %u, largest block = %u\n",
|
|
usTotalFree, usLargestBlock);
|
|
}
|
|
|
|
xmsError = XmsAllocateExtendedMemory(usLargestBlock, &usBlockHandle);
|
|
|
|
if (xmsError != XMS_SUCCESS)
|
|
{
|
|
printf("Error allocating extended memory - %s\n", XmsErrorString(xmsError));
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
** Lock the block and obtain its linear address. Then ensure that the
|
|
** image fits into it.
|
|
*/
|
|
|
|
xmsError = XmsLockExtendedMemory(usBlockHandle, &ulLinearAddress);
|
|
|
|
if (xmsError != XMS_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf("Error locking extended memory - %s\n", XmsErrorString(xmsError));
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (bVerbose)
|
|
{
|
|
/*
|
|
** Print info about block allocated
|
|
*/
|
|
|
|
fprintf(stderr, "\r \r");
|
|
printf("Block allocated at 0x%lX\n", ulLinearAddress);
|
|
}
|
|
|
|
/*
|
|
** Zero upper memory in CHUNKSIZE chunks
|
|
*/
|
|
|
|
memset(ucBuffer, 0, sizeof(ucBuffer));
|
|
ulSectionSize = (ULONG)usLargestBlock * 1024;
|
|
#if 1
|
|
for (ulSectionOffset = 0; ulSectionOffset < ulSectionSize; ulSectionOffset += usReadSize)
|
|
{
|
|
if ((ulSectionSize - ulSectionOffset) < CHUNKSIZE)
|
|
{
|
|
usReadSize = (USHORT)(ulSectionSize - ulSectionOffset);
|
|
}
|
|
else
|
|
{
|
|
usReadSize = CHUNKSIZE;
|
|
}
|
|
|
|
xmsError = XmsMoveExtendedMemory(
|
|
0, (ULONG)(UCHAR far *)ucBuffer,
|
|
usBlockHandle, ulSectionOffset, usReadSize);
|
|
|
|
if (xmsError != XMS_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf("Error zeroing extended memory - %s\n", XmsErrorString(xmsError));
|
|
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Open image file
|
|
*/
|
|
if (bSerialDownload)
|
|
OEMInitDebugSerial();
|
|
if (bParallelDownload || bSerialDownload) {
|
|
//
|
|
// Prepare boot packet
|
|
//
|
|
pDestByte = BootPacket;
|
|
for (i = 0; i < BOOT_HEADER_SIZE; i++) {
|
|
*pDestByte++ = BootHeader[i];
|
|
}
|
|
|
|
chksum = 0;
|
|
len = 9;
|
|
|
|
if (pszFileName) {
|
|
if (bSerialDownload)
|
|
printf("Loading image %s via serial port.\r\n",pszFileName);
|
|
else
|
|
printf("Loading image %s via parallel port.\r\n",pszFileName);
|
|
bootType = 1; // The NULL byte
|
|
for (pTemp = pszFileName; *pTemp; pTemp++) {
|
|
bootType++;
|
|
}
|
|
|
|
len += bootType;
|
|
|
|
} else {
|
|
if (bSerialDownload)
|
|
printf("Loading host default image via serial port.\r\n");
|
|
else
|
|
printf("Loading host default image via parallel port.\r\n");
|
|
bootType = BOOT_TYPE;
|
|
}
|
|
|
|
uiTemp = len;
|
|
for (i = 0; i < 2; i++) {
|
|
*pDestByte++ = (unsigned char)(uiTemp & 0xFF);
|
|
chksum += (uiTemp & 0xFF);
|
|
uiTemp >>= 8;
|
|
}
|
|
|
|
uiTemp = bootType;
|
|
for (i = 0; i < 4; i++) {
|
|
*pDestByte++ = (unsigned char)(uiTemp & 0xFF);
|
|
chksum += (uiTemp & 0xFF);
|
|
uiTemp >>= 8;
|
|
}
|
|
|
|
if (bootType > 0) {
|
|
for (pTemp = pszFileName; *pTemp; pTemp++) {
|
|
*pDestByte++ = *pTemp;
|
|
chksum += *pTemp;
|
|
}
|
|
*pDestByte++ = 0;
|
|
}
|
|
|
|
*pDestByte++ = (unsigned char)((~chksum) & 0xFF);
|
|
|
|
for (i = 0; i < BOOT_TAIL_SIZE; i++) {
|
|
*pDestByte++ = BootTail[i];
|
|
}
|
|
if (bVerbose)
|
|
printf("Sending boot packet: ");
|
|
usIndex=0;
|
|
while (&BootPacket[usIndex] < pDestByte) {
|
|
if (NoPPFS)
|
|
return FALSE;
|
|
if (bVerbose)
|
|
printf("%x ",BootPacket[usIndex]);
|
|
if (bSerialDownload)
|
|
OEMWriteDebugByte(BootPacket[usIndex]);
|
|
else
|
|
OEMParallelPortSendByte(BootPacket[usIndex]);
|
|
usIndex++;
|
|
}
|
|
if (bVerbose)
|
|
printf("Sent.\r\n");
|
|
} else {
|
|
hImage = _open(pszFileName, _O_BINARY | _O_RDONLY);
|
|
|
|
if (hImage == -1)
|
|
{
|
|
printf("%s: Error opening file - %s\n", pszFileName, _strerror(NULL));
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ((lImageSize = _filelength(hImage)) == -1)
|
|
{
|
|
printf("%s: Error obtaining file size - %s\n", pszFileName, _strerror(NULL));
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
if (bVerbose)
|
|
{
|
|
printf("Loading %s, size = %ld\n", pszFileName, lImageSize);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Read initial signature and physical start and size
|
|
*/
|
|
|
|
usReadSize = sizeof(ucSignature) + 2 * sizeof(ULONG);
|
|
|
|
if (DownloadRead(hImage, &ucBuffer, usReadSize, bParallelDownload) != (int)usReadSize)
|
|
{
|
|
printf("Error reading signature - %s\n", _strerror(NULL));
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (memcmp(ucBuffer, ucSignature, sizeof(ucSignature)) != 0)
|
|
{
|
|
printf("Error invalid signature\nData: ");
|
|
for (i=0; i<usReadSize; i++)
|
|
printf("%x ",ucBuffer[i]);
|
|
printf("\r\n");
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ulReadTotal=*(PULONG)&ucBuffer[sizeof(ucSignature) + sizeof(ULONG)];
|
|
if (bVerbose)
|
|
{
|
|
/*
|
|
** Print Physical start and size
|
|
*/
|
|
|
|
printf(
|
|
"Image physical start = 0x%8.8lX, size = %ld\n",
|
|
*(PULONG)&ucBuffer[sizeof(ucSignature)],
|
|
*(PULONG)&ucBuffer[sizeof(ucSignature) + sizeof(ULONG)]);
|
|
}
|
|
// Initialize the percent thingie.
|
|
DrawPercent((DWORD)-1, (DWORD)"");
|
|
|
|
/*
|
|
** Copy file to upper memory in CHUNKSIZE chunks
|
|
*/
|
|
|
|
for ( ; ; )
|
|
{
|
|
usAmountRead = DownloadRead(hImage, ucBuffer, 3 * sizeof(ULONG), bParallelDownload);
|
|
ulReadProgress+=12;
|
|
if (usAmountRead != 3 * sizeof(ULONG))
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf("Error reading header - %s\n", XmsErrorString(xmsError));
|
|
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ulSectionAddress = *(PULONG)&ucBuffer[0];
|
|
ulSectionSize = *(PULONG)&ucBuffer[4];
|
|
ulSectionChecksum = *(PULONG)&ucBuffer[8];
|
|
|
|
if (ulSectionAddress == 0)
|
|
{
|
|
*pulEntryPoint = ulSectionSize;
|
|
|
|
break;
|
|
}
|
|
|
|
if (ulSectionAddress < ulLinearAddress ||
|
|
(ulSectionAddress + ulSectionSize) >
|
|
(ulLinearAddress + (ULONG)usLargestBlock * 1024))
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf(
|
|
"Error image section doesn't fit in allocated block\n"
|
|
"Block allocated at 0x%lX, size = %ld\n"
|
|
"Section physical start = 0x%8.8lX, size = %ld\n",
|
|
ulLinearAddress, (ULONG)usLargestBlock * 1024,
|
|
ulSectionAddress, ulSectionSize);
|
|
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (bVerbose)
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf(
|
|
"Section physical start = 0x%8.8lX, size = %ld\n",
|
|
ulSectionAddress, ulSectionSize);
|
|
}
|
|
|
|
ulChecksum = 0;
|
|
|
|
for (ulSectionOffset = 0; ulSectionOffset < ulSectionSize; )
|
|
{
|
|
if ((ulSectionSize - ulSectionOffset) < CHUNKSIZE)
|
|
{
|
|
usReadSize = (USHORT)(ulSectionSize - ulSectionOffset);
|
|
}
|
|
else
|
|
{
|
|
usReadSize = CHUNKSIZE;
|
|
}
|
|
usAmountRead = DownloadRead(hImage, ucBuffer, usReadSize,bParallelDownload);
|
|
|
|
if (usAmountRead != usReadSize)
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf("Error reading section - %s\n", XmsErrorString(xmsError));
|
|
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
ulReadProgress+= usReadSize;
|
|
DrawPercent(ulReadProgress, ulReadTotal);
|
|
#if 0
|
|
|
|
for (usIndex = 0; usIndex < usAmountRead; usIndex++)
|
|
{
|
|
ulChecksum += ucBuffer[usIndex];
|
|
}
|
|
#endif
|
|
#if 1
|
|
xmsError = XmsMoveExtendedMemory(
|
|
0, (ULONG)(UCHAR far *)ucBuffer,
|
|
usBlockHandle, ulSectionAddress - ulLinearAddress + ulSectionOffset,
|
|
(usAmountRead + 1) & ~1U);
|
|
|
|
if (xmsError != XMS_SUCCESS)
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf("Error moving extended memory - %s\n", XmsErrorString(xmsError));
|
|
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
ulSectionOffset += usAmountRead;
|
|
}
|
|
#if 0
|
|
if (ulChecksum != ulSectionChecksum)
|
|
{
|
|
fprintf(stderr, "\r \r");
|
|
printf(
|
|
"Bad checksum 0x%8.8lX, expected 0x%8.8lX\n",
|
|
ulChecksum, ulSectionChecksum);
|
|
|
|
XmsUnlockExtendedMemory(usBlockHandle);
|
|
|
|
XmsFreeExtendedMemory(usBlockHandle);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DrawPercent(ulReadTotal, ulReadTotal);
|
|
if (!bParallelDownload && !bSerialDownload)
|
|
_close(hImage);
|
|
|
|
/*
|
|
** Stop the floppy motor in case it contained the image file
|
|
*/
|
|
|
|
__asm
|
|
{
|
|
push dx
|
|
mov dx, 03F2h ; Floppy motor and DMA control
|
|
in al, dx
|
|
and al, 00Fh ; Clear motor on bits
|
|
out dx, al
|
|
pop dx
|
|
}
|
|
fprintf(stderr, "\r \r");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
UCHAR
|
|
GetPCIConfigMechanism()
|
|
{
|
|
UCHAR ucPCIVersionMajor;
|
|
UCHAR ucPCIVersionMinor;
|
|
UCHAR ucPCIBus;
|
|
UCHAR ucPCIConfigMech;
|
|
|
|
__asm
|
|
{
|
|
mov ax, 0xB101
|
|
int 0x1A
|
|
|
|
jc noPCI
|
|
|
|
cmp dx, 0x4350 ; 'CP'
|
|
|
|
jne noPCI
|
|
|
|
or ah, ah
|
|
jnz noPCI
|
|
|
|
mov ucPCIVersionMajor, bh
|
|
mov ucPCIVersionMinor, bl
|
|
mov ucPCIBus, cl
|
|
|
|
and al, 0x03
|
|
mov ucPCIConfigMech, al
|
|
}
|
|
|
|
printf(
|
|
"%d PCI bus%s (Version %X.%2.2X) using Configuration Mechanism # %d\n",
|
|
ucPCIBus + 1, ucPCIBus == 0 ? "" : "ses",
|
|
ucPCIVersionMajor, ucPCIVersionMinor, ucPCIConfigMech);
|
|
|
|
return (ucPCIBus << 2) | ucPCIConfigMech;
|
|
|
|
noPCI:
|
|
printf("PCI bus not detected\n");
|
|
|
|
return 0;
|
|
}
|