📄 ppfs.c
字号:
/* * NK Kernel ppfs client code * * Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. * * Module Name: * * ppfs.c * * Abstract: * * This file implements the NK kernel ppfs client side interface * * */#include "kernel.h"#include "ethdbg.h"#include "halether.h"/* All strings must be <= 128 bytes including the null termination *//* Message format: (assume little endians, lower address first> * -4 0 4 N-1 N N+4 * AA5555AA<header><data><checksum>5AA50A1A * * Header format: * 0 2 4 * <opcode><length> * lsb msb * * Length is 16 bit value. It includes all fields (== N) * Opcode is 16 bit value. Current values are: * 0x0000 - boot (AA5555AA00000500FA5AA50A1A) * 0x0001 - init (AA5555AA01000500F95AA50A1A) * 0x0002 - open * 0x0003 - close * 0x0004 - read * 0x0005 - write * 0x0006 - seek * 0x0007 - delete * 0x0008 - findfirst * 0x0009 - findnext * 0x000A - rRegGet * 0x000B - rRegOpen * 0x000C - rRegClose * 0x000D - rRegEnum * * * Reply to a message will have the same opcode. Bit15 is set to * indicate transmission failure. * * Data is stream of bytes * * Checksum is ~(sum of preceding N-1 bytes) * * Length of data is <length> - 5 * */extern CRITICAL_SECTION ppfscs;extern int NoPPFS; // parallel port not present flag// If PPFS is running over ethernet, buffer up as much data as possible (up to// EDBG_MAX_DATA_SIZE) to send to the other side. The PpfsEthBuf memory is set// up through the EdbgRegisterDfltClient call.extern BOOL BufferedPPFS;extern UCHAR *PpfsEthBuf;// Local state variables for handling translation of the packet based ethernet// commands to the byte read write commands used by the ppfs engine.static UCHAR *pWritePtr, *pReadPtr;static DWORD dwRemainingBytes;static DWORD dwBytesWrittenToBuffer;void (* lpParallelPortSendByteFunc)(BYTE ch);int (* lpParallelPortGetByteFunc)(void);// Routines for handling the buffering for PPFS over ether.BOOL fill_edbg_buffer(){ DWORD dwLen = EDBG_MAX_DATA_SIZE; if (!pEdbgRecv(EDBG_SVC_PPSH, PpfsEthBuf,&dwLen, INFINITE)) { NoPPFS = TRUE; return FALSE; } dwRemainingBytes = dwLen; pReadPtr = PpfsEthBuf; return TRUE;}BOOL write_edbg_buffer(){ if (dwBytesWrittenToBuffer && !pEdbgSend(EDBG_SVC_PPSH,PpfsEthBuf,dwBytesWrittenToBuffer)) { NoPPFS = TRUE; return FALSE; } dwBytesWrittenToBuffer = 0; pWritePtr = PpfsEthBuf; return TRUE;}// Functions for lpParallelPortxxxByteFunc, set up by calling// SetKernelCommDev(KERNEL_SVC_PPSH,KERNEL_COMM_ETHER).void ppfs_send_byte_ether(BYTE ch){ *pWritePtr++ = ch; if (++dwBytesWrittenToBuffer == EDBG_MAX_DATA_SIZE) write_edbg_buffer();}int ppfs_get_byte_ether(){ // Refill buffer if necessary and return next byte if (dwRemainingBytes == 0) fill_edbg_buffer(); dwRemainingBytes--; return *pReadPtr++;}int read_value(int *chksum) { int loop; int result; BYTE ch; for (loop = 0; loop < sizeof(int); loop++ ) { ch = lpParallelPortGetByteFunc(); *chksum += ch; ((LPBYTE)&result)[loop] = ch; } return result;}void write_value(int val, int *chksum) { int loop; BYTE ch; for (loop = 0; loop < 4; loop++) { ch = ((LPBYTE)&val)[loop]; *chksum += ch; lpParallelPortSendByteFunc(ch); }}int read_header(int *chksum) { if (BufferedPPFS && !fill_edbg_buffer()) return -1; if (read_value(chksum) != 0xaa5555aa) return -1; *chksum = 0; return read_value(chksum);}void write_header(int cmd, int *chksum) { if (BufferedPPFS) { dwBytesWrittenToBuffer = 0; pWritePtr = PpfsEthBuf; } write_value(0xaa5555aa,chksum); *chksum = 0; write_value(cmd,chksum);}void read_data(LPBYTE buf, int cnt, int *chksum) { BYTE ch; while (cnt--) { ch = lpParallelPortGetByteFunc(); *chksum += ch; *buf++ = ch; }}void write_data(LPBYTE buf, int cnt, int *chksum) { while (cnt--) { *chksum += *buf; lpParallelPortSendByteFunc(*buf++); }}/* returns TRUE if success, FALSE if failure */BOOL read_end(int checksum) { BYTE b; int tmp; b = lpParallelPortGetByteFunc(); if (((checksum & 0xff) != b) || (read_value(&tmp) != 0x1a0aa55a)) return FALSE; return TRUE;}void write_end(int checksum) { int tmp; BYTE ch = ((checksum & 0xff) ^ 0xff); lpParallelPortSendByteFunc(ch); write_value(0x1a0aa55a,&tmp); /* Write out end of message signature */ // If we're using ethernet, packet is all formatted and ready to go, send now if (BufferedPPFS) write_edbg_buffer();}int rlseeknocs(int fd, int off, int mode) { int chksum, result; if (NoPPFS) return -1; write_header(0x00110006,&chksum); /* opcode = 0x0006, length = 17 */ write_value(fd,&chksum); write_value(off,&chksum); write_value(mode,&chksum); write_end(chksum); if (read_header(&chksum) != 0x00090006) /* opcode = 0x0006, length = 9 */ return -1; result = read_value(&chksum); if (!read_end(chksum)) return -1; return result;}int rlseek(int fd, int off, int mode) { int result; EnterCriticalSection(&ppfscs); result = rlseeknocs(fd,off,mode); LeaveCriticalSection(&ppfscs); return result;}int rwriteshort(int fd, char *buf, int cnt) { int chksum, result; write_header(0x000d0005+(cnt<<16), &chksum); /* opcode = 0x0005, length = 13 + cnt */ write_value(fd,&chksum); write_value(cnt,&chksum); write_data(buf,cnt,&chksum); write_end(chksum); if (read_header(&chksum) != 0x00090005) /* opcode = 0x0005, length = 9 */ return -1; result = read_value(&chksum); if (!read_end(chksum)) return -1; return result;}int rwrite(int fd, char *buf, int cnt) { int csize, fullsize; int result, result2; char *buf2 = buf; if (NoPPFS) return -1; fullsize = cnt; LockPages(buf,fullsize,0,LOCKFLAG_READ); EnterCriticalSection(&ppfscs); result2 = 0; while (cnt) { csize = ( cnt > 32*1024 ? 32*1024 : cnt); if ((result = rwriteshort(fd,buf2,csize)) == -1) { result2 = -1; break; } result2 += result; cnt -= csize; buf2 += csize; } LeaveCriticalSection(&ppfscs); UnlockPages(buf,fullsize); return result2;}int rreadshort(int fd, char *buf, int cnt) { int chksum, result, size; write_header(0x000d0004, &chksum); /* opcode = 0x0004, length = 13 */ write_value(fd, &chksum); write_value(cnt,&chksum); write_end(chksum); result = read_header(&chksum); if ((result & 0xffff) != 0x0004) return -1; size = ((result >> 16) & 0xffff) - 9; /* subtract header & chksum */ result = read_value(&chksum); read_data(buf,size,&chksum); if (!read_end(chksum)) return -1; return result;}int rreadnocs(int fd, char *buf, int cnt) { int csize, fullsize; int result, result2; char *buf2 = buf; if (NoPPFS) return -1; fullsize = cnt; result2 = 0; while (cnt) { csize = ( cnt > 32*1024 ? 32*1024 : cnt); if ((result = rreadshort(fd,buf2,csize)) == -1) { result2 = -1; break; } result2 += result; cnt -= csize; buf2 += csize; } return result2;}int rread(int fd, char *buf, int cnt) { int result; if (NoPPFS) return -1; LockPages(buf,cnt,0,LOCKFLAG_WRITE); EnterCriticalSection(&ppfscs); result = rreadnocs(fd,buf,cnt); LeaveCriticalSection(&ppfscs); UnlockPages(buf,cnt); return result;}int rreadseek(int fd, char *buf, int cnt, int pos) { int ret; LockPages(buf,cnt,0,LOCKFLAG_WRITE); EnterCriticalSection(&ppfscs); ret = rlseeknocs(fd,pos,0); if (ret != pos) ret = 0; else ret = rreadnocs(fd,buf,cnt); LeaveCriticalSection(&ppfscs); UnlockPages(buf,cnt); return ret;}int rclose(int fd) { int chksum, result; EnterCriticalSection(&ppfscs); if (NoPPFS) { LeaveCriticalSection(&ppfscs); return -1; } write_header(0x00090003, &chksum); /* opcode = 0x0003, length = 9 */ write_value(fd,&chksum); write_end(chksum); if (read_header(&chksum) != 0x00090003) { LeaveCriticalSection(&ppfscs); return -1; } result = read_value(&chksum); if (!read_end(chksum)) { LeaveCriticalSection(&ppfscs); return -1; } LeaveCriticalSection(&ppfscs); return result;}#define MAX_FILENAME_LEN 256void SC_PPSHRestart(void) { NoPPFS = 0;}int ropen(WCHAR *name, int mode) { int chksum, result, len; char fname[MAX_FILENAME_LEN]; len = strlenW(name)+1; KUnicodeToAscii(fname,name,MAX_FILENAME_LEN); if (NoPPFS) return -1; EnterCriticalSection(&ppfscs); write_header(0x00090002 + (len<<16), &chksum); /* opcode = 0x0002, length = 9 + strlen + 1 */ write_value(mode,&chksum); write_data(fname,len,&chksum); write_end(chksum); if (read_header(&chksum) != 0x00090002) { LeaveCriticalSection(&ppfscs); return -1; } result = read_value(&chksum); if (!read_end(chksum)) { LeaveCriticalSection(&ppfscs); return -1; } LeaveCriticalSection(&ppfscs); return result;}// Registration database access functions for kernel debug support initializationint rRegOpen(DWORD hKey, CHAR *szName, LPDWORD lphKey) { int chksum, len; if (NoPPFS) return -1; len = strlen(szName)+1; EnterCriticalSection(&ppfscs); write_header(0x0009000B + (len<<16), &chksum); /* opcode = 0x000B, length = 9 + strlen + 1 */ write_value(hKey,&chksum); write_data(szName,len,&chksum); write_end(chksum); if (read_header(&chksum) != 0x0009000B) { LeaveCriticalSection(&ppfscs); return -1; } *lphKey = read_value(&chksum); if (!read_end(chksum)) { LeaveCriticalSection(&ppfscs); return -1; } LeaveCriticalSection(&ppfscs); return 0;}int rRegClose(DWORD hKey) { int chksum, result; if (NoPPFS) return -1; EnterCriticalSection(&ppfscs); write_header(0x0009000C, &chksum); /* opcode = 0x000C, length = 9 */ write_value(hKey,&chksum); write_end(chksum); if (read_header(&chksum) != 0x0009000C) { LeaveCriticalSection(&ppfscs); return -1; } result = read_value(&chksum); if (!read_end(chksum)) { LeaveCriticalSection(&ppfscs); return -1; } LeaveCriticalSection(&ppfscs); return result;}int rRegGet(DWORD hKey, CHAR *szName, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpdwSize) { int chksum, result, len; if (NoPPFS) return -1; len = strlen(szName)+1; EnterCriticalSection(&ppfscs); write_header(0x0009000A + (len<<16), &chksum); /* opcode = 0x000A, length = 9 + strlen + 1 */ write_value(hKey,&chksum); write_data(szName,len,&chksum); write_end(chksum); result = read_header(&chksum); if ((result & 0xffff) != 0x000A) { LeaveCriticalSection(&ppfscs); return 0; } len = ((result >> 16) & 0xffff) - 9; /* subtract header & chksum */ *lpdwType = read_value(&chksum); *lpdwSize = len; read_data(lpbData,len,&chksum); if (!read_end(chksum)) { LeaveCriticalSection(&ppfscs); return 0; } LeaveCriticalSection(&ppfscs); return 1;}int rRegEnum(DWORD hKey, DWORD dwIndex, LPBYTE lpbData, LPDWORD lpdwSize) { int chksum, result, len; if (NoPPFS) return -1; EnterCriticalSection(&ppfscs); write_header(0x000D000D, &chksum); /* opcode = 0x000A, length = 13 */ write_value(hKey,&chksum); write_value(dwIndex,&chksum); write_end(chksum); result = read_header(&chksum); if ((result & 0xffff) != 0x000D) { LeaveCriticalSection(&ppfscs); return -1; } len = ((result >> 16) & 0xffff) - 9; /* subtract header & chksum */ result = read_value(&chksum); *lpdwSize = len; read_data(lpbData,len,&chksum); if (!read_end(chksum)) { LeaveCriticalSection(&ppfscs); return -1; } LeaveCriticalSection(&ppfscs); return result;}// Routine for sending debug messages over PPSH. Note the problem with the PPFS CS here -// if we are called to put out a debug message while in a sys call, we can't block on the CS,// but we can't just start sending data, because if someone is called into the loader, the// other end will get confused (PPFS protocol can't handle packets within other packets).#define MAX_DEBUGSTRING_LEN 512// Prevent multiple LOW per HIGHADJ fixup problem#if defined(PPC)#pragma optimize("", off)#endifvoid PpfsWriteDebugString(unsigned short *name) { int chksum, len; char fname[MAX_DEBUGSTRING_LEN]; if (NoPPFS) return; if (!InSysCall()) EnterCriticalSection(&ppfscs); else if (ppfscs.OwnerThread) { // Can't block and someone is using the loader, just dump message to debug serial port OEMWriteDebugString(name); return; } len = strlenW(name)+1; KUnicodeToAscii(fname,name,MAX_DEBUGSTRING_LEN); write_header(0x0009000f + (len<<16), &chksum); /* opcode = 0x000f, length = 9 + strlen + 1 */ write_value(len,&chksum); write_data(fname,len,&chksum); write_end(chksum); if (!InSysCall()) LeaveCriticalSection(&ppfscs); return;}#if defined(PPC)#pragma optimize("", on)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -