xref: /rkdeveloptool/RKImage.cpp (revision 76af099afcbcafd97801028de2ba3421d3c12865)
1*76af099aSliuyi /*
2*76af099aSliuyi  * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd
3*76af099aSliuyi  * Seth Liu 2017.03.01
4*76af099aSliuyi  *
5*76af099aSliuyi  * SPDX-License-Identifier:	GPL-2.0+
6*76af099aSliuyi  */
7*76af099aSliuyi #include "RKImage.h"
8*76af099aSliuyi 
9*76af099aSliuyi DWORD CRKImage::GetVersion()
10*76af099aSliuyi {
11*76af099aSliuyi 	return m_version;
12*76af099aSliuyi }
13*76af099aSliuyi DWORD CRKImage::GetMergeVersion()
14*76af099aSliuyi {
15*76af099aSliuyi 	return m_mergeVersion;
16*76af099aSliuyi }
17*76af099aSliuyi STRUCT_RKTIME CRKImage::GetReleaseTime()
18*76af099aSliuyi {
19*76af099aSliuyi 	return m_releaseTime;
20*76af099aSliuyi }
21*76af099aSliuyi ENUM_RKDEVICE_TYPE CRKImage::GetSupportDevice()
22*76af099aSliuyi {
23*76af099aSliuyi 	return m_supportDevice;
24*76af099aSliuyi }
25*76af099aSliuyi ENUM_OS_TYPE CRKImage::GetOsType()
26*76af099aSliuyi {
27*76af099aSliuyi 	UINT *pOsType;
28*76af099aSliuyi 	pOsType = (UINT *)&m_reserved[4];
29*76af099aSliuyi 	return (ENUM_OS_TYPE)*pOsType;
30*76af099aSliuyi }
31*76af099aSliuyi 
32*76af099aSliuyi USHORT CRKImage::GetBackupSize()
33*76af099aSliuyi {
34*76af099aSliuyi 	USHORT *pBackupSize;
35*76af099aSliuyi 	pBackupSize = (USHORT *)&m_reserved[12];
36*76af099aSliuyi 	return *pBackupSize;
37*76af099aSliuyi }
38*76af099aSliuyi DWORD CRKImage::GetBootOffset()
39*76af099aSliuyi {
40*76af099aSliuyi 	return m_bootOffset;
41*76af099aSliuyi }
42*76af099aSliuyi DWORD CRKImage::GetBootSize()
43*76af099aSliuyi {
44*76af099aSliuyi 	return m_bootSize;
45*76af099aSliuyi }
46*76af099aSliuyi DWORD CRKImage::GetFWOffset()
47*76af099aSliuyi {
48*76af099aSliuyi 	return m_fwOffset;
49*76af099aSliuyi }
50*76af099aSliuyi long long CRKImage::GetFWSize()
51*76af099aSliuyi {
52*76af099aSliuyi 	return m_fwSize;
53*76af099aSliuyi }
54*76af099aSliuyi bool CRKImage::SaveBootFile(string filename)
55*76af099aSliuyi {
56*76af099aSliuyi 	FILE *file = NULL;
57*76af099aSliuyi 	int iRead;
58*76af099aSliuyi 	file = fopen(filename.c_str(), "wb+");
59*76af099aSliuyi 	if (!file) {
60*76af099aSliuyi 		return false;
61*76af099aSliuyi 	}
62*76af099aSliuyi 	BYTE buffer[1024];
63*76af099aSliuyi 	DWORD dwBufferSize = 1024;
64*76af099aSliuyi 	DWORD dwBootSize = m_bootSize;
65*76af099aSliuyi 	DWORD dwReadSize;
66*76af099aSliuyi 	fseek(m_pFile, m_bootOffset, SEEK_SET);
67*76af099aSliuyi 	do {
68*76af099aSliuyi 		dwReadSize = (dwBootSize >= 1024) ? dwBufferSize : dwBootSize;
69*76af099aSliuyi 		iRead = fread(buffer, 1, dwReadSize, m_pFile);
70*76af099aSliuyi 		if (iRead != (int)dwReadSize) {
71*76af099aSliuyi 			fclose(file);
72*76af099aSliuyi 			return false;
73*76af099aSliuyi 		}
74*76af099aSliuyi 		fwrite(buffer, 1, dwReadSize, file);
75*76af099aSliuyi 		dwBootSize -= dwReadSize;
76*76af099aSliuyi 	} while(dwBootSize > 0);
77*76af099aSliuyi 	fclose(file);
78*76af099aSliuyi 	return true;
79*76af099aSliuyi }
80*76af099aSliuyi bool CRKImage::SaveFWFile(string filename)
81*76af099aSliuyi {
82*76af099aSliuyi 	FILE *file = NULL;
83*76af099aSliuyi 	int iRead;
84*76af099aSliuyi 	file = fopen(filename.c_str(), "wb+");
85*76af099aSliuyi 	if (!file) {
86*76af099aSliuyi 		return false;
87*76af099aSliuyi 	}
88*76af099aSliuyi 	BYTE buffer[1024];
89*76af099aSliuyi 	DWORD dwBufferSize = 1024;
90*76af099aSliuyi 	long long dwFWSize = m_fwSize;
91*76af099aSliuyi 	DWORD dwReadSize;
92*76af099aSliuyi 	fseeko(m_pFile, m_fwOffset, SEEK_SET);
93*76af099aSliuyi 	do {
94*76af099aSliuyi 		dwReadSize = (dwFWSize >= 1024) ? dwBufferSize : dwFWSize;
95*76af099aSliuyi 		iRead = fread(buffer, 1, dwReadSize, m_pFile);
96*76af099aSliuyi 		if (iRead != (int)dwReadSize) {
97*76af099aSliuyi 			fclose(file);
98*76af099aSliuyi 			return false;
99*76af099aSliuyi 		}
100*76af099aSliuyi 		fwrite(buffer, 1, dwReadSize, file);
101*76af099aSliuyi 		dwFWSize -= dwReadSize;
102*76af099aSliuyi 	} while (dwFWSize > 0);
103*76af099aSliuyi 	fclose(file);
104*76af099aSliuyi 	return true;
105*76af099aSliuyi }
106*76af099aSliuyi bool CRKImage::GetData(long long dwOffset, DWORD dwSize, PBYTE lpBuffer)
107*76af099aSliuyi {
108*76af099aSliuyi 	if ( (dwOffset < 0) || (dwSize == 0) ) {
109*76af099aSliuyi 		return false;
110*76af099aSliuyi 	}
111*76af099aSliuyi 	if ( dwOffset+dwSize > m_fileSize) {
112*76af099aSliuyi 		return false;
113*76af099aSliuyi 	}
114*76af099aSliuyi 	fseeko(m_pFile, dwOffset, SEEK_SET);
115*76af099aSliuyi 	UINT uiActualRead;
116*76af099aSliuyi 	uiActualRead = fread(lpBuffer,1, dwSize, m_pFile);
117*76af099aSliuyi 	if (dwSize != uiActualRead){
118*76af099aSliuyi 		return false;
119*76af099aSliuyi 	}
120*76af099aSliuyi 	return true;
121*76af099aSliuyi }
122*76af099aSliuyi void CRKImage::GetReservedData(PBYTE &lpData, USHORT &usSize)
123*76af099aSliuyi {
124*76af099aSliuyi 	lpData = m_reserved;
125*76af099aSliuyi 	usSize = IMAGE_RESERVED_SIZE;
126*76af099aSliuyi }
127*76af099aSliuyi 
128*76af099aSliuyi CRKImage::CRKImage(string filename, bool &bCheck)
129*76af099aSliuyi {
130*76af099aSliuyi 	Version.setContainer(this);
131*76af099aSliuyi 	Version.getter(&CRKImage::GetVersion);
132*76af099aSliuyi 	MergeVersion.setContainer(this);
133*76af099aSliuyi 	MergeVersion.getter(&CRKImage::GetMergeVersion);
134*76af099aSliuyi 	ReleaseTime.setContainer(this);
135*76af099aSliuyi 	ReleaseTime.getter(&CRKImage::GetReleaseTime);
136*76af099aSliuyi 	SupportDevice.setContainer(this);
137*76af099aSliuyi 	SupportDevice.getter(&CRKImage::GetSupportDevice);
138*76af099aSliuyi 	OsType.setContainer(this);
139*76af099aSliuyi 	OsType.getter(&CRKImage::GetOsType);
140*76af099aSliuyi 	BackupSize.setContainer(this);
141*76af099aSliuyi 	BackupSize.getter(&CRKImage::GetBackupSize);
142*76af099aSliuyi 	BootOffset.setContainer(this);
143*76af099aSliuyi 	BootOffset.getter(&CRKImage::GetBootOffset);
144*76af099aSliuyi 	BootSize.setContainer(this);
145*76af099aSliuyi 	BootSize.getter(&CRKImage::GetBootSize);
146*76af099aSliuyi 	FWOffset.setContainer(this);
147*76af099aSliuyi 	FWOffset.getter(&CRKImage::GetFWOffset);
148*76af099aSliuyi 	FWSize.setContainer(this);
149*76af099aSliuyi 	FWSize.getter(&CRKImage::GetFWSize);
150*76af099aSliuyi 	SignFlag.setContainer(this);
151*76af099aSliuyi 	SignFlag.getter(&CRKImage::GetSignFlag);
152*76af099aSliuyi 	struct stat statBuf;
153*76af099aSliuyi 	m_bootObject = NULL;
154*76af099aSliuyi 	m_pFile = NULL;
155*76af099aSliuyi 	m_bSignFlag = false;
156*76af099aSliuyi 
157*76af099aSliuyi 	m_signMd5Size = 0;
158*76af099aSliuyi 	memset(m_md5, 0, 32);
159*76af099aSliuyi 	memset(m_signMd5, 0, 256);
160*76af099aSliuyi 
161*76af099aSliuyi 	char szName[256];
162*76af099aSliuyi 	strcpy(szName, filename.c_str());
163*76af099aSliuyi 	if(stat(szName, &statBuf) < 0) {
164*76af099aSliuyi 		bCheck = false;
165*76af099aSliuyi 		return;
166*76af099aSliuyi 	}
167*76af099aSliuyi 	if (S_ISDIR(statBuf.st_mode)) {
168*76af099aSliuyi 		bCheck = false;
169*76af099aSliuyi 		return;
170*76af099aSliuyi 	}
171*76af099aSliuyi 	m_fileSize = statBuf.st_size;
172*76af099aSliuyi 
173*76af099aSliuyi 	bool bOnlyBootFile=false;
174*76af099aSliuyi 	transform(filename.begin(), filename.end(), filename.begin(), (int(*)(int))tolower);
175*76af099aSliuyi 	if (filename.find(".bin") != string::npos) {
176*76af099aSliuyi 		bOnlyBootFile = true;
177*76af099aSliuyi 	}
178*76af099aSliuyi 
179*76af099aSliuyi 	m_pFile = fopen(szName, "rb");
180*76af099aSliuyi 	if (!m_pFile) {
181*76af099aSliuyi 		bCheck = false;
182*76af099aSliuyi 		return;
183*76af099aSliuyi 	}
184*76af099aSliuyi 
185*76af099aSliuyi 	int nMd5DataSize, iRead;
186*76af099aSliuyi 	long long ulFwSize;
187*76af099aSliuyi 	STRUCT_RKIMAGE_HEAD imageHead;
188*76af099aSliuyi 	if (!bOnlyBootFile) {
189*76af099aSliuyi 		fseeko(m_pFile, 0, SEEK_SET);
190*76af099aSliuyi 		iRead = fread((PBYTE)(&imageHead), 1, sizeof(STRUCT_RKIMAGE_HEAD), m_pFile);
191*76af099aSliuyi 		if (iRead != sizeof(STRUCT_RKIMAGE_HEAD)) {
192*76af099aSliuyi 			bCheck = false;
193*76af099aSliuyi 			return;
194*76af099aSliuyi 		}
195*76af099aSliuyi 		if ( imageHead.uiTag != 0x57464B52 ) {
196*76af099aSliuyi 			bCheck = false;
197*76af099aSliuyi 			return;
198*76af099aSliuyi 		}
199*76af099aSliuyi 		if ((imageHead.reserved[14] == 'H') && (imageHead.reserved[15] == 'I')) {
200*76af099aSliuyi 			ulFwSize = *((DWORD *)(&imageHead.reserved[16]));
201*76af099aSliuyi 			ulFwSize <<= 32;
202*76af099aSliuyi 			ulFwSize += imageHead.dwFWOffset;
203*76af099aSliuyi 			ulFwSize += imageHead.dwFWSize;
204*76af099aSliuyi 		} else
205*76af099aSliuyi 			ulFwSize = imageHead.dwFWOffset + imageHead.dwFWSize;
206*76af099aSliuyi 		nMd5DataSize = GetImageSize() - ulFwSize;
207*76af099aSliuyi 		if (nMd5DataSize >= 160) {
208*76af099aSliuyi 			m_bSignFlag = true;
209*76af099aSliuyi 			m_signMd5Size = nMd5DataSize - 32;
210*76af099aSliuyi 			fseeko(m_pFile, ulFwSize, SEEK_SET);
211*76af099aSliuyi 			iRead = fread(m_md5, 1, 32, m_pFile);
212*76af099aSliuyi 			if (iRead != 32) {
213*76af099aSliuyi 				bCheck = false;
214*76af099aSliuyi 				return;
215*76af099aSliuyi 			}
216*76af099aSliuyi 			iRead = fread(m_signMd5, 1, nMd5DataSize - 32, m_pFile);
217*76af099aSliuyi 			if (iRead != (nMd5DataSize - 32)) {
218*76af099aSliuyi 				bCheck = false;
219*76af099aSliuyi 				return;
220*76af099aSliuyi 			}
221*76af099aSliuyi 		} else {
222*76af099aSliuyi 			fseeko(m_pFile, -32, SEEK_END);
223*76af099aSliuyi 			iRead = fread(m_md5, 1, 32, m_pFile);
224*76af099aSliuyi 			if (iRead != 32) {
225*76af099aSliuyi 				bCheck = false;
226*76af099aSliuyi 				return;
227*76af099aSliuyi 			}
228*76af099aSliuyi 		}
229*76af099aSliuyi 
230*76af099aSliuyi 		m_version = imageHead.dwVersion;
231*76af099aSliuyi 		m_mergeVersion = imageHead.dwMergeVersion;
232*76af099aSliuyi 		m_releaseTime.usYear = imageHead.stReleaseTime.usYear;
233*76af099aSliuyi 		m_releaseTime.ucMonth = imageHead.stReleaseTime.ucMonth;
234*76af099aSliuyi 		m_releaseTime.ucDay = imageHead.stReleaseTime.ucDay;
235*76af099aSliuyi 		m_releaseTime.ucHour = imageHead.stReleaseTime.ucHour;
236*76af099aSliuyi 		m_releaseTime.ucMinute = imageHead.stReleaseTime.ucMinute;
237*76af099aSliuyi 		m_releaseTime.ucSecond = imageHead.stReleaseTime.ucSecond;
238*76af099aSliuyi 		m_supportDevice = imageHead.emSupportChip;
239*76af099aSliuyi 		m_bootOffset = imageHead.dwBootOffset;
240*76af099aSliuyi 		m_bootSize = imageHead.dwBootSize;
241*76af099aSliuyi 		m_fwOffset = imageHead.dwFWOffset;
242*76af099aSliuyi 		m_fwSize = ulFwSize - m_fwOffset;
243*76af099aSliuyi 		memcpy(m_reserved, imageHead.reserved, IMAGE_RESERVED_SIZE);
244*76af099aSliuyi 	} else {
245*76af099aSliuyi 		m_bootOffset = 0;
246*76af099aSliuyi 		m_bootSize = m_fileSize;
247*76af099aSliuyi 	}
248*76af099aSliuyi 
249*76af099aSliuyi 	PBYTE lpBoot;
250*76af099aSliuyi 	lpBoot = new BYTE[m_bootSize];
251*76af099aSliuyi 	fseeko(m_pFile, m_bootOffset, SEEK_SET);
252*76af099aSliuyi 	iRead = fread(lpBoot, 1, m_bootSize, m_pFile);
253*76af099aSliuyi 	if (iRead != (int)m_bootSize) {
254*76af099aSliuyi 		bCheck = false;
255*76af099aSliuyi 		return;
256*76af099aSliuyi 	}
257*76af099aSliuyi 	bool bRet;
258*76af099aSliuyi 	m_bootObject = new CRKBoot(lpBoot, m_bootSize, bRet);
259*76af099aSliuyi 	if (!bRet) {
260*76af099aSliuyi 		bCheck = false;
261*76af099aSliuyi 		return;
262*76af099aSliuyi 	}
263*76af099aSliuyi 	if (bOnlyBootFile) {
264*76af099aSliuyi 		m_supportDevice = m_bootObject->SupportDevice;
265*76af099aSliuyi 		UINT *pOsType;
266*76af099aSliuyi 		pOsType = (UINT *)&m_reserved[4];
267*76af099aSliuyi 		*pOsType = (UINT)RK_OS;
268*76af099aSliuyi 		fclose(m_pFile);
269*76af099aSliuyi 		m_pFile = NULL;
270*76af099aSliuyi 	}
271*76af099aSliuyi 	bCheck = true;
272*76af099aSliuyi }
273*76af099aSliuyi CRKImage::~CRKImage()
274*76af099aSliuyi {
275*76af099aSliuyi 	if (m_pFile) {
276*76af099aSliuyi 		fclose(m_pFile);
277*76af099aSliuyi 		m_pFile = NULL;
278*76af099aSliuyi 	}
279*76af099aSliuyi 	if (m_bootObject) {
280*76af099aSliuyi 		delete m_bootObject;
281*76af099aSliuyi 		m_bootObject = NULL;
282*76af099aSliuyi 	}
283*76af099aSliuyi }
284*76af099aSliuyi 
285*76af099aSliuyi long long CRKImage::GetImageSize()
286*76af099aSliuyi {
287*76af099aSliuyi 	return m_fileSize;
288*76af099aSliuyi }
289*76af099aSliuyi int CRKImage::GetMd5Data(PBYTE &lpMd5, PBYTE &lpSignMd5)
290*76af099aSliuyi {
291*76af099aSliuyi 	lpMd5 = m_md5;
292*76af099aSliuyi 	lpSignMd5 = m_signMd5;
293*76af099aSliuyi 	return m_signMd5Size;
294*76af099aSliuyi }
295*76af099aSliuyi bool CRKImage::GetSignFlag()
296*76af099aSliuyi {
297*76af099aSliuyi 	return m_bSignFlag;
298*76af099aSliuyi }