WINCE6.0设备ID写入和读取的实现


 机身码写入到设备中,一般是写入EEPROM或是FLASH中,EEPROM更为可靠,但因为产品中没有EEPROM,所以就只能写在FLASH中了。

 

对于WINCE6.0系统来说,bootloader都会为至少TOC分配一块,如果机身码信息量比较小,可以考虑写在TOC所在的块中,但如果信息量大,可以专门指定一个block来保存机身码。

 

1.      保存机身码的变量定义

我们机身码目前只有8个字节,信息量比较小,可以保存在TOC所在的block中,TOC结构体定义如下:

typedef struct _TOC {

typedef struct _TOC {
    DWORD               dwSignature;
    // How to boot the images in this TOC.
    // This could be moved into the image descriptor if desired,
    // but I prefer to conserve space.
    BOOT_CFG            BootCfg;

    // Array of Image Descriptors.
    IMAGE_DESCRIPTOR    id[MAX_TOC_DESCRIPTORS];

    CHAININFO           chainInfo;
	UINT8    CwDeviceId[8];//kandi add at 2013.09.17

} TOC, *PTOC;           // 512 bytes


我们定义了UINT8    CwDeviceId[8]用于保存机身码。实现的思路是在FMD驱动中写入,在eboot读取出来并保存到BSP_ARGS结构体中,这样开机之后就可以取出机身码了,此结构体定义如下:

typedef struct {
	OAL_ARGS_HEADER header;
	UINT8 deviceId[16];                 // Device identification
	OAL_KITL_ARGS kitl;
	UINT8 uuid[16];
	BOOL bUpdateMode;                   // TRUE = Enter update mode on reboot.
	BOOL bHiveCleanFlag;                // TRUE = Clean hive at boot
	BOOL bCleanBootFlag;                // TRUE = Clear RAM, hive, user store at boot
	BOOL bFormatPartFlag;               // TRUE = Format partion when mounted at boot
	DWORD    nfsblk;

	HANDLE g_SDCardDetectEvent; //kim
	DWORD g_SDCardState ;
	DWORD dwLcdType;
	BOOL ChargingState;///<TRUE--->charge full
	UINT8 CwDeviceId[8];//kandi add at 2013.09.17
} BSP_ARGS, *PBSP_ARGS;


定义了UINT8 CwDeviceId[8],用于保存从TOC block中读取的机身码。

 

2.      机身码的读写

我们把机身码的写入放在FMD驱动中FMD_OEMIoControl函数中实现,应用层通过DeviceIoControl的方式来调用,首先就涉及到控制码的定义,如下:

#define IOCTL_DISK_USER_START 0x7E0
#define IOCTL_DISK_BASE FILE_DEVICE_DISK

#define IOCTL_DISK_USER(Function) \
    CTL_CODE( IOCTL_DISK_BASE, IOCTL_DISK_USER_START+Function, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_FMD_WRITE_DEVICE_ID              IOCTL_DISK_USER(13)
#define IOCTL_FMD_READ_DEVICE_ID              IOCTL_DISK_USER(14)

机身码的读写是通过BOOL control_device_id(PBYTE pInBuf, DWORD nInBufSize,BOOLaction,DWORD block)函数来实现的,pInBuf参数传递进来要写入的机身码,nInBufSize表示机身码长度,action表示读或是写的动作,block表示是从TOC还是专门指定的block中读写,此函数实现如下:

BOOL control_device_id(PBYTE pInBuf, DWORD nInBufSize,BOOL action,DWORD block)
{
	BOOL result = TRUE;
	
	BSP_ARGS *pBsp_Args = (BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START;
	SectorInfo si, si2;
	DWORD i=0, SectorValue=0, BlockValue;
	CHAR			g_PageBuf[LB_PAGE_SIZE];
	const PTOC 		g_pTOC = (PTOC)&g_PageBuf;

	if(action)
	{
		RETAILMSG(1, (TEXT(" control_device_id() --->write device id\r\n")));
		if ( !FMD_ReadSector(BLOCK_TO_SECTOR(block), (PUCHAR)g_PageBuf, &si, 1) )
		{
			RETAILMSG(1, (TEXT("control_device_id() : failed to read block (0x%x).\r\n"), block));
			return FALSE;
		}

		if (!FMD_EraseBlock(block))
		{
			RETAILMSG(1, (TEXT("control_device_id(): failed to erase block (0x%x).\r\n"), block));
			return FALSE;
		}

		// setup our metadata so filesys won't stomp us
		si.dwReserved1 = 0;
		si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
		si.bBadBlock = BADBLOCKMARK;
		si.wReserved2 = 0;

		if(nInBufSize > DEVICE_ID_LENGTH)
		{
			nInBufSize = DEVICE_ID_LENGTH;
		}


		for(i=0;i<nInBufSize;i++)
		{
			if(block == TOC_BLOCK)
			{
				g_pTOC->CwDeviceId[i] = pInBuf[i];
			}
			else
			{
				g_PageBuf[i] = pInBuf[i];
			}
			
		}
		
		if ( !FMD_WriteSector(BLOCK_TO_SECTOR(block), (PUCHAR)&g_PageBuf, &si, 1) )
		{
			RETAILMSG(1, (TEXT("control_device_id(): failed to write block (0x%x).\r\n"), block));
			return FALSE;
		}
		
	}
	else
	{
		// read it back 
		RETAILMSG(1, (TEXT(" control_device_id()--->read device id\r\n")));
		
		if ( !FMD_ReadSector(BLOCK_TO_SECTOR(block), (PUCHAR)&g_PageBuf, &si2, 1) )
		{
			RETAILMSG(1, (TEXT("control_device_id() : failed to read block (0x%x).\r\n"), block));
			return FALSE;
		}
		else
		{
			memset(pBSPArgs->CwDeviceId,0x0,DEVICE_ID_LENGTH);
			
			if(block == TOC_BLOCK)
			{
				memcpy(pBSPArgs->CwDeviceId, g_pTOC->CwDeviceId, nInBufSize);
			}
			else
			{
				memcpy(pBSPArgs->CwDeviceId, g_PageBuf, nInBufSize);
			}


			for(i=0;i<nInBufSize;i++)
			{
				RETAILMSG(TRUE,(TEXT(" write_device_id() --->after write device_id[%d] : 0x%x \r\n"),i, pBSPArgs->CwDeviceId[i])); 
			}
		}
	}

	return result;

}


在实现此函数过程遇到一系列的问题,总结如下:

⑴编译问题,因为要在fmd.cpp中实现机身码的写入及读取动作,需要用到eboot中loader.h的定义,可通过下面两种方式较为方便引用loader.h函数:

其一:

在fmd.cpp中包含#include <..\\..\\..\\BOOTLOADER\\Eboot\\Eboot\\loader.h>

其二:

在fmd文件夹下Sources文件的INCLUDES=后面增加$(_TARGETPLATROOT)\SRC\BOOTLOADER\Eboot\Eboot

在fmd.cpp中包含#include "loader.h"

 

⑵写入时导致系统DataAbort问题,主要是指针操作的问题,一定要让指针指向分配好的内存区域。

⑶在向block写入数据之前一定要先擦除,否则无法成功写入。

 

设备启动时,在eboot阶段的OEMPlatformInit函数调用void read_device_id(DWORD block)函数来从FLASH获得机身码,此函数定义如下:

BOOL  read_device_id(DWORD block)
{
	UINT8 i=0;
	static UCHAR        SectorBuf[LB_PAGE_SIZE];
	const PTOC 		pTOCBuf = (PTOC)&SectorBuf;

	if ( !FMD_ReadSector(BLOCK_TO_SECTOR(block), (PUCHAR)&SectorBuf, NULL, 1) )
	{
		RETAILMSG(1, (TEXT(" Read id: Unable to read/verify TOC\r\n")));
		return FALSE;
	}
	else
	{
		if(block ==TOC_BLOCK)
		{
			memcpy(pBSPArgs->CwDeviceId, pTOCBuf->CwDeviceId, DEVICE_ID_LENGTH);
			RETAILMSG(1, (TEXT(" Read device id from Toc sector\r\n")));
		}
		else
		{
			memcpy(pBSPArgs->CwDeviceId, SectorBuf, DEVICE_ID_LENGTH);
			RETAILMSG(1, (TEXT(" Read device id from sysm info sector\r\n")));
		}
		
		for(i=0;i<DEVICE_ID_LENGTH;i++)
		{
			RETAILMSG(TRUE,(TEXT(" read_device_id[%d] : 0x%x\r\n"),i,pBSPArgs->CwDeviceId[i]) );   //bad
		}
	}

	return TRUE;
} 


3.      应用程序读写机身码

在实现过程中遇到下面一些问题:

⑴ DeviceIoControl函数控制码不规范问题,刚开始随便定义#define IOCTL_FMD_WRITE_DEVICE_ID 1之前这么使用是没有问题的,但这里这么使用就有问题,通过调用GetLastError()函数获得返回值为87,在winerror.h中找到此值对应含义如下:

//

// MessageId: ERROR_INVALID_PARAMETER

//

// MessageText:

//

// The parameter is incorrect.

//

#define ERROR_INVALID_PARAMETER          87L    // dderror

原来是控制参数无效,才意识到这个问题,重新定义如下:

#define IOCTL_DISK_USER_START 0x7E0
#define IOCTL_DISK_USER_END   0x7FF
#define IOCTL_DISK_BASE FILE_DEVICE_DISK

#define METHOD_BUFFERED                 0
#define FILE_ANY_ACCESS                 0

#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

#define IOCTL_DISK_USER(Function) \
    CTL_CODE( IOCTL_DISK_BASE, IOCTL_DISK_USER_START+Function, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_FMD_WRITE_DEVICE_ID              IOCTL_DISK_USER(13)


才解决了这个问题。

⑵Cstring和char转换问题

 

写函数的实现如下:

void CDeviceIDDlg::OnBnClickedWriteDeviceId()
{
	// TODO: Add your control notification handler code here
	BOOL status = TRUE;
	DWORD result=0, i=0, nSize=0,nLength=0;
	CString cstemp = L"",csDeviceId = L"";


	GetDlgItem(IDC_EDIT_WRITE_DEVICE_ID)->GetWindowText(cstemp);

	nLength=cstemp.GetLength();

	if(nLength > DEVICE_ID_MAX)
	{
		nLength = DEVICE_ID_MAX;
	}

	nSize = WideCharToMultiByte(CP_ACP,NULL,cstemp.GetBuffer(nLength),-1,NULL,0,NULL,FALSE);
	char *szDeviceId=new char[nSize];
	WideCharToMultiByte(CP_ACP,NULL,cstemp.GetBuffer(nLength),-1,szDeviceId,nSize,NULL,FALSE);

	g_DeviceIDhandle = CreateFile(L"XXX:", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0 ,0);

	if(g_DeviceIDhandle == INVALID_HANDLE_VALUE)
	{
		AfxMessageBox(L"DSK3 OPEN FAILD!");
	}

	status = DeviceIoControl(g_DeviceIDhandle, IOCTL_FMD_WRITE_DEVICE_ID,(LPVOID)szDeviceId, nLength, NULL, 0, NULL, NULL);
	if(status == 0)
	{
		result = GetLastError();
		NKDbgPrintfW(TEXT("OnBnClickedWriteDeviceId()--->GetLastError()=0x%x\r\n"),status,result);
	}
	
}


 

读函数实现如下:

void CDeviceIDDlg::OnBnClickedReadDeviceId()
{
	// TODO: Add your control notification handler code here
	CString csDeviceID=L"";
	DWORD dwRead = 0,i=0, widecharlen=0;
	char *szDeviceID=new char[DEVICE_ID_MAX];


	SetDlgItemText(IDC_EDIT_READ_DEVICE_ID, L"");
	if(KernelIoControl(IOCTL_HAL_GET_DEVICEID, NULL, 0, szDeviceID, DEVICE_ID_MAX, &dwRead) == FALSE)
	{
		NKDbgPrintfW(TEXT("GetDeviceID()--->error\r\n"));
	}
	else
	{
		widecharlen = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, szDeviceID, -1, 0, 0); 
		csDeviceID.GetBuffer(widecharlen);
		MultiByteToWideChar(CP_ACP, MB_COMPOSITE, szDeviceID, -1, csDeviceID.GetBuffer(widecharlen), widecharlen);
	}

	SetDlgItemText(IDC_EDIT_READ_DEVICE_ID, csDeviceID);
	csDeviceID.ReleaseBuffer(); 
}


 

你可能感兴趣的:(WINCE6.0设备ID写入和读取的实现)