#include #include #include "itsutils.h" #include "kernelmisc.h" //-------------------------------------------------------- DWORD DoMagicianFlashRom(DWORD dwOffset, DWORD dwSize, DWORD dwChecksum, BYTE *pBuffer) { struct FlashAccessCommand { DWORD dwCommand; DWORD pbDestAddr; DWORD pbSrcAddr; DWORD dwLength; } cmd; cmd.dwCommand= 0; cmd.pbDestAddr= dwOffset; cmd.pbSrcAddr= (DWORD)pBuffer; cmd.dwLength= dwSize; DWORD dwReturned; DWORD res= 0; debug("flashrom: erase %d buf=%08lx dst=%08lx len=%08lx\n", cmd.dwCommand, cmd.pbSrcAddr, cmd.pbDestAddr, cmd.dwLength); if (!KernelIoControl(0x01012a10, &cmd, sizeof(cmd), NULL, 0, &dwReturned)) { res= GetLastError(); if (res==0) res= ERROR_GEN_FAILURE; debug("flashaccess: erase: error=%08lx: %08lx\n", res, dwReturned); return res; } cmd.dwCommand= 1; cmd.pbDestAddr= dwOffset; cmd.pbSrcAddr= (DWORD)pBuffer; cmd.dwLength= dwSize; debug("flashrom: write %d buf=%08lx dst=%08lx len=%08lx\n", cmd.dwCommand, cmd.pbSrcAddr, cmd.pbDestAddr, cmd.dwLength); if (!KernelIoControl(0x01012a10, &cmd, sizeof(cmd), NULL, 0, &dwReturned)) { res= GetLastError(); if (res==0) res= ERROR_GEN_FAILURE; debug("flashaccess: write: error=%08lx: %08lx\n", res, dwReturned); return res; } return res; } #define IOCTL_HAL_OAK_START 5000 #define IOCTL_HAL_XIP_BASE IOCTL_HAL_OAK_START + 500 /*++ IOCTL_HAL_WRITE_XIP Writes an XIP region to flash Input Buffer is a WRITE_XIP_HEADER followed immediately by dwNumRecords of XIP_RECORD_INFO structures Output buffer is unused. --*/ #define IOCTL_HAL_WRITE_XIP_3 CTL_CODE(FILE_DEVICE_HAL, IOCTL_HAL_XIP_BASE + 1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_HAL_WRITE_XIP_4 CTL_CODE(FILE_DEVICE_HAL, 0x2e, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct _WRITE_XIP_HEADER { LPVOID pvPhysAddr; // physical starting address of XIP DWORD dwLength; // length of XIP DWORD dwNumRecords; // number of records in XIP } WRITE_XIP_HEADER, *PWRITE_XIP_HEADER; typedef struct _XIP_RECORD_INFO { LPVOID pvPhysStart; // physical starting address of record, dest addr DWORD dwPhysLen; // physical len, in bytes of record DWORD dwCheckSum; // sum of all the bytes in the record data VOID UNALIGNED * pvRAMStart; // virtual address of record in RAM, source addr } XIP_RECORD_INFO, *PXIP_RECORD_INFO; DWORD DoXipFlashRom(DWORD dwOffset, DWORD dwSize, DWORD dwChecksum, BYTE *pBuffer) { struct { WRITE_XIP_HEADER hdr; XIP_RECORD_INFO info; } xipcmd; xipcmd.hdr.pvPhysAddr= (void*)dwOffset; xipcmd.hdr.dwLength= dwSize; xipcmd.hdr.dwNumRecords= 1; xipcmd.info.pvPhysStart= (void*)dwOffset; xipcmd.info.dwPhysLen= dwSize; xipcmd.info.dwCheckSum= dwChecksum; xipcmd.info.pvRAMStart= (VOID*)pBuffer; DWORD ioctlcode; if (GetWinceVersion()<4) ioctlcode=IOCTL_HAL_WRITE_XIP_3; else ioctlcode=IOCTL_HAL_WRITE_XIP_4; DWORD dwResult; DWORD dwReturned; DWORD res= 0; debug("flashrom: csum=%08lx ioctl=%08lx buf=%08lx dst=%08lx len=%08lx\n", xipcmd.info.dwCheckSum, ioctlcode, xipcmd.info.pvRAMStart, xipcmd.info.pvPhysStart, xipcmd.info.dwPhysLen); if (!KernelIoControl(ioctlcode, &xipcmd, sizeof(xipcmd), &dwResult, sizeof(DWORD), &dwReturned)) { res= GetLastError(); if (res==0) res= ERROR_GEN_FAILURE; } debug("flashxip: error=%08lx: %08lx %08lx\n", res, dwResult, dwReturned); return res; } ITSUTILS_API HRESULT STDAPICALLTYPE ITFlashROM( DWORD cbInput, FlashROMParams *pbInput, DWORD *pcbOutput, FlashROMResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= sizeof(FlashROMResult); FlashROMResult *pOut= *ppbOutput= (FlashROMResult*)LocalAlloc(LPTR, *pcbOutput); KernelMode _km; DWORD res= 0; switch (pbInput->dwType) { case FLASH_TYPE_XIPFLASH: res= DoXipFlashRom(pbInput->dwOffset, pbInput->dwSize, pbInput->dwCheckSum, pbInput->buffer); break; case FLASH_TYPE_MAGICIAN: res= DoMagicianFlashRom(pbInput->dwOffset, pbInput->dwSize, pbInput->dwCheckSum, pbInput->buffer); break; default: debug("ERROR: unknown flash type %d\n", pbInput->dwType); } pOut->dwResult= res; debug("flashrom: error=%08lx: %08lx\n", res, pOut->dwResult); return res; }