📄 main.c
字号:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID SC_WriteDebugLED(WORD wIndex, DWORD dwPattern) {
return;
}
//------------------------------------------------------------------------------
BYTE CMOS_Read( BYTE offset )
{
BYTE cAddr, cResult;
// Remember, we only change the low order 5 bits in address register
cAddr = _inp( CMOS_ADDR );
_outp( CMOS_ADDR, (cAddr & RTC_ADDR_MASK) | offset );
cResult = _inp( CMOS_DATA );
return (cResult);
}
BOOL IsTimeEqual(LPSYSTEMTIME lpst1, LPSYSTEMTIME lpst2)
{
if (lpst1->wYear != lpst2->wYear) return(FALSE);
if (lpst1->wMonth != lpst2->wMonth) return(FALSE);
if (lpst1->wDayOfWeek != lpst2->wDayOfWeek) return(FALSE);
if (lpst1->wDay != lpst2->wDay) return(FALSE);
if (lpst1->wHour != lpst2->wHour) return(FALSE);
if (lpst1->wMinute != lpst2->wMinute) return(FALSE);
if (lpst1->wSecond != lpst2->wSecond) return(FALSE);
return (TRUE);
}
// RTC routines from kernel\hal\x86\rtc.c
BOOL
Bare_GetRealTime(LPSYSTEMTIME lpst)
{
SYSTEMTIME st;
LPSYSTEMTIME lpst1 = &st, lpst2 = lpst, lptmp;
lpst1->wSecond = 61; // initialize to an invalid value
lpst2->wSecond = 62; // initialize to an invalid value
do {
// exchange lpst1 and lpst2
lptmp = lpst1;
lpst1 = lpst2;
lpst2 = lptmp;
// wait until not updating
while (CMOS_Read(RTC_STATUS_A) & RTC_SRA_UIP);
// Read all the values.
lpst1->wYear = CMOS_Read(RTC_YEAR);
lpst1->wMonth = CMOS_Read(RTC_MONTH);
lpst1->wDayOfWeek = CMOS_Read(RTC_DO_WEEK);
lpst1->wDay = CMOS_Read(RTC_DO_MONTH);
lpst1->wHour = CMOS_Read(RTC_HOUR);
lpst1->wMinute = CMOS_Read(RTC_MINUTE);
lpst1->wSecond = CMOS_Read(RTC_SECOND);
} while (!IsTimeEqual (lpst1, lpst2));
lpst->wMilliseconds = 0; // No easy way to read Milliseconds, returning 0 is safe
if (!(CMOS_Read (RTC_STATUS_B) & RTC_SRB_DM)) {
// Values returned in BCD.
lpst->wSecond = DECODE_BCD(lpst->wSecond);
lpst->wMinute = DECODE_BCD(lpst->wMinute);
lpst->wHour = DECODE_BCD(lpst->wHour);
lpst->wDay = DECODE_BCD(lpst->wDay);
lpst->wDayOfWeek = DECODE_BCD(lpst->wDayOfWeek);
lpst->wMonth = DECODE_BCD(lpst->wMonth);
lpst->wYear = DECODE_BCD(lpst->wYear);
}
// OK - PC RTC returns 1998 as 98.
lpst->wYear += (lpst->wYear > 70)? 1900 : 2000;
return (TRUE);
}
//------------------------------------------------------------------------------
// OEMGetSecs
//
// Return a count of seconds from some arbitrary time (the absolute value
// is not important, so long as it increments appropriately).
//
//------------------------------------------------------------------------------
DWORD
OEMGetSecs()
{
SYSTEMTIME st;
Bare_GetRealTime( &st );
return ((60UL * (60UL * (24UL * (31UL * st.wMonth + st.wDay) + st.wHour) + st.wMinute)) + st.wSecond);
}
//------------------------------------------------------------------------------
UCHAR CalcChksum(PUCHAR pBuf, USHORT len)
//------------------------------------------------------------------------------
{
USHORT s = 0;
UCHAR csum = 0;
for(s = 0; s < len; s++)
csum += *(pBuf + s);
return csum;
}
//------------------------------------------------------------------------------
BOOL SerialSendBootRequest(VOID)
//------------------------------------------------------------------------------
{
BYTE buffer[sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BOOT_REQUEST)] = {0};
PSERIAL_PACKET_HEADER pHeader = (PSERIAL_PACKET_HEADER)buffer;
PSERIAL_BOOT_REQUEST pBootReq = (PSERIAL_BOOT_REQUEST)(buffer + sizeof(SERIAL_PACKET_HEADER));
// create boot request
strcpy(pBootReq->PlatformId, PLATFORM_STRING);
// create header
memcpy(pHeader->headerSig, packetHeaderSig, HEADER_SIG_BYTES);
pHeader->pktType = KS_PKT_DLREQ;
pHeader->payloadSize = sizeof(SERIAL_BOOT_REQUEST);
pHeader->crcData = CalcChksum((PBYTE)pBootReq, sizeof(SERIAL_BOOT_REQUEST));
pHeader->crcHdr = CalcChksum((PBYTE)pHeader,
sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr));
OEMSerialSendRaw(buffer, sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BOOT_REQUEST));
return TRUE;
}
//------------------------------------------------------------------------------
BOOL SerialSendBlockAck(DWORD uBlockNumber)
//------------------------------------------------------------------------------
{
BYTE buffer[sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BLOCK_HEADER)];
PSERIAL_PACKET_HEADER pHeader = (PSERIAL_PACKET_HEADER)buffer;
PSERIAL_BLOCK_HEADER pBlockAck = (PSERIAL_BLOCK_HEADER)(buffer + sizeof(SERIAL_PACKET_HEADER));
// create block ack
pBlockAck->uBlockNum = uBlockNumber;
// create header
memcpy(pHeader->headerSig, packetHeaderSig, HEADER_SIG_BYTES);
pHeader->pktType = KS_PKT_DLACK;
pHeader->payloadSize = sizeof(SERIAL_BLOCK_HEADER);
pHeader->crcData = CalcChksum((PBYTE)pBlockAck, sizeof(SERIAL_BLOCK_HEADER));
pHeader->crcHdr = CalcChksum((PBYTE)pHeader,
sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr));
OEMSerialSendRaw(buffer, sizeof(SERIAL_PACKET_HEADER) + sizeof(SERIAL_BLOCK_HEADER));
return TRUE;
}
//------------------------------------------------------------------------------
BOOL WaitForBootAck(BOOL *pfJump)
//
// This function will fail if a boot ack is not received in a timely manner
// so that another boot request can be sent
//------------------------------------------------------------------------------
{
BOOL fRet = FALSE;
USHORT cbBuffer = KITL_MTU;
SERIAL_PACKET_HEADER header = {0};
PSERIAL_BOOT_ACK pBootAck = (PSERIAL_BOOT_ACK)g_buffer;
EdbgOutputDebugString("Waiting for boot ack...\r\n");
if(RecvPacket(&header, g_buffer, &cbBuffer, FALSE))
{
// header checksum already verified
if(KS_PKT_DLACK == header.pktType &&
sizeof(SERIAL_BOOT_ACK) == header.payloadSize)
{
EdbgOutputDebugString("Received boot ack\r\n");
*pfJump = pBootAck->fJumping;
fRet = TRUE;
}
}
return fRet;
}
//------------------------------------------------------------------------------
BOOL WaitForJump(VOID)
//
// waits indefinitely for jump command
//------------------------------------------------------------------------------
{
USHORT cbBuffer = KITL_MTU;
SERIAL_PACKET_HEADER header = {0};
PSERIAL_JUMP_REQUEST pJumpReq = (PSERIAL_JUMP_REQUEST)g_buffer;
// wait indefinitely for a jump request
while(1)
{
if(RecvPacket(&header, g_buffer, &cbBuffer, TRUE))
{
// header & checksum already verified
if(KS_PKT_JUMP == header.pktType &&
sizeof(SERIAL_JUMP_REQUEST) == header.payloadSize)
{
pBootArgs->KitlTransport = (WORD)pJumpReq->dwKitlTransport;
SerialSendBlockAck(0);
return TRUE;
}
}
}
// never reached
return FALSE;
}
#define TIMEOUT_RECV 3 // seconds
//------------------------------------------------------------------------------
BOOL RecvPacket(PSERIAL_PACKET_HEADER pHeader, PBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite)
//------------------------------------------------------------------------------
{
// receive header
if(!RecvHeader(pHeader, bWaitInfinite))
{
EdbgOutputDebugString("failed to receive header\r\n");
return FALSE;
}
// verify packet checksum
if(pHeader->crcHdr != CalcChksum((PBYTE)pHeader,
sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr)))
{
EdbgOutputDebugString("header checksum failure\r\n");
return FALSE;
}
// make sure sufficient buffer is provided
if(*pcbFrame < pHeader->payloadSize)
{
EdbgOutputDebugString("insufficient buffer size; ignoring packet\r\n");
return FALSE;
}
// receive data
*pcbFrame = pHeader->payloadSize;
if(!OEMSerialRecvRaw(pbFrame, pcbFrame, bWaitInfinite))
{
EdbgOutputDebugString("failed to read packet data\r\n");
return FALSE;
}
// verify data checksum
if(pHeader->crcData != CalcChksum(pbFrame, *pcbFrame))
{
EdbgOutputDebugString("data checksum failure\r\n");
return FALSE;
}
// verify packet type -- don't return any packet that is not
// a type the bootloader expects to receive
if(KS_PKT_DLPKT != pHeader->pktType &&
KS_PKT_DLACK != pHeader->pktType &&
KS_PKT_JUMP != pHeader->pktType)
{
EdbgOutputDebugString("received non-download packet type\r\n");
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
BOOL RecvHeader(PSERIAL_PACKET_HEADER pHeader, BOOLEAN bWaitInfinite)
//------------------------------------------------------------------------------
{
USHORT cbRead;
UINT i = 0;
cbRead = sizeof(UCHAR);
// read the header bytes
while(i < HEADER_SIG_BYTES)
{
if(!OEMSerialRecvRaw((PBYTE)&(pHeader->headerSig[i]), &cbRead, bWaitInfinite) || sizeof(UCHAR) != cbRead)
{
EdbgOutputDebugString("failed to receive header signature\r\n");
return FALSE;
}
if(pHeader->headerSig[i] == packetHeaderSig[i])
{
i++;
}
else
{
i = 0;
}
}
// read the remaining header
cbRead = sizeof(SERIAL_PACKET_HEADER) - HEADER_SIG_BYTES;
if(!OEMSerialRecvRaw((PUCHAR)pHeader + HEADER_SIG_BYTES, &cbRead, bWaitInfinite) ||
sizeof(SERIAL_PACKET_HEADER) - HEADER_SIG_BYTES != cbRead)
{
EdbgOutputDebugString("failed to receive header data\r\n");
return FALSE;
}
// verify the header checksum
if(pHeader->crcHdr != CalcChksum((PUCHAR)pHeader,
sizeof(SERIAL_PACKET_HEADER) - sizeof(pHeader->crcHdr)))
{
EdbgOutputDebugString("header checksum fail\r\n");
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
BOOL OEMSerialRecvRaw(LPBYTE pbFrame, PUSHORT pcbFrame, BOOLEAN bWaitInfinite)
//------------------------------------------------------------------------------
{
USHORT ct = 0;
DWORD tStart = 0;
UCHAR uStatus = 0;
UCHAR uCtrl = READ_PORT_UCHAR(DlIoPortBase+comModemControl) & ~COM_RTS;
WRITE_PORT_UCHAR(DlIoPortBase+comModemControl, (UCHAR)(uCtrl | COM_RTS));
for(ct = 0; ct < *pcbFrame; ct++)
{
if (!bWaitInfinite)
{
tStart = OEMGetSecs();
}
while(!(LS_RX_DATA_READY & (uStatus = READ_PORT_UCHAR(DlIoPortBase+comLineStatus))))
{
if(!bWaitInfinite && (OEMGetSecs() - tStart > TIMEOUT_RECV))
{
*pcbFrame = 0;
WRITE_PORT_UCHAR(DlIoPortBase+comModemControl, (UCHAR)(uCtrl));
return FALSE;
}
}
// check and clear comm errors
if(LS_RX_ERRORS & uStatus)
{
// clear the queue
WRITE_PORT_UCHAR(DlIoPortBase+comFIFOControl, 0x07);
*pcbFrame = 0;
WRITE_PORT_UCHAR(DlIoPortBase+comModemControl, (UCHAR)(uCtrl));
EdbgOutputDebugString("Comm errors have occurred; status = 0x%x\r\n", uStatus);
return FALSE;
}
*(pbFrame + ct) = READ_PORT_UCHAR(DlIoPortBase+comRxBuffer);
}
WRITE_PORT_UCHAR(DlIoPortBase+comModemControl, (UCHAR)(uCtrl));
return TRUE;
}
//------------------------------------------------------------------------------
BOOL OEMSerialSendRaw(LPBYTE pbFrame, USHORT cbFrame)
//------------------------------------------------------------------------------
{
UINT ct;
// block until send is complete; no timeout
for(ct = 0; ct < cbFrame; ct++)
{
// check that send transmitter holding register is empty
while(!(READ_PORT_UCHAR(DlIoPortBase+comLineStatus) & LS_THR_EMPTY))
(VOID)NULL;
// write character to port
WRITE_PORT_UCHAR(DlIoPortBase+comTxBuffer, (UCHAR)*(pbFrame+ct));
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -