summaryrefslogtreecommitdiff
path: root/gpxe/src/arch/i386/core/wince_loader.c
blob: f452b659b8af31548458aac9ac2c139e5d1c8767 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#define LOAD_DEBUG	0

static int get_x_header(unsigned char *data, unsigned long now);
static void jump_2ep();
static unsigned char ce_signature[] = {'B', '0', '0', '0', 'F', 'F', '\n',};
static char ** ep;

#define BOOT_ARG_PTR_LOCATION 0x001FFFFC

typedef struct _BOOT_ARGS{
	unsigned char ucVideoMode;
	unsigned char ucComPort;
	unsigned char ucBaudDivisor;
	unsigned char ucPCIConfigType;
	
	unsigned long dwSig;
	#define BOOTARG_SIG 0x544F4F42
	unsigned long dwLen;
	
	unsigned char ucLoaderFlags;
	unsigned char ucEshellFlags;
	unsigned char ucEdbgAdapterType;
	unsigned char ucEdbgIRQ;
	
	unsigned long dwEdbgBaseAddr;
	unsigned long dwEdbgDebugZone;	
	unsigned long dwDHCPLeaseTime;
	unsigned long dwEdbgFlags;
	
	unsigned long dwEBootFlag;
	unsigned long dwEBootAddr;
	unsigned long dwLaunchAddr;
	
	unsigned long pvFlatFrameBuffer;
	unsigned short vesaMode;
	unsigned short cxDisplayScreen;
	unsigned short cyDisplayScreen;
	unsigned short cxPhysicalScreen;
	unsigned short cyPhysicalScreen;
	unsigned short cbScanLineLength;
	unsigned short bppScreen;
	
	unsigned char RedMaskSize;
	unsigned char REdMaskPosition;
	unsigned char GreenMaskSize;
	unsigned char GreenMaskPosition;
	unsigned char BlueMaskSize;
	unsigned char BlueMaskPosition;
} BOOT_ARGS;

BOOT_ARGS BootArgs;

static struct segment_info{
	unsigned long addr;		// Section Address
	unsigned long size;		// Section Size
	unsigned long checksum;		// Section CheckSum
} X;

#define PSIZE	(1500)			//Max Packet Size
#define DSIZE  (PSIZE+12)
static unsigned long dbuffer_available =0;
static unsigned long not_loadin =0;
static unsigned long d_now =0;

unsigned long entry;
static unsigned long ce_curaddr;


static sector_t ce_loader(unsigned char *data, unsigned int len, int eof);
static os_download_t wince_probe(unsigned char *data, unsigned int len)
{
	if (strncmp(ce_signature, data, sizeof(ce_signature)) != 0) {
		return 0;
	}
	printf("(WINCE)");
	return ce_loader;
}

static sector_t ce_loader(unsigned char *data, unsigned int len, int eof)
{
	static unsigned char dbuffer[DSIZE];
	int this_write = 0;
	static int firsttime = 1;

	/*
	 *	new packet in, we have to 
	 *	[1] copy data to dbuffer,
	 *
	 *	update...
	 *	[2]  dbuffer_available
	 */
	memcpy( (dbuffer+dbuffer_available), data, len);	//[1]
	dbuffer_available += len;	// [2]
	len = 0;

	d_now = 0;
	
#if 0
	printf("dbuffer_available =%ld \n", dbuffer_available);
#endif 
	
	if (firsttime) 
	{
		d_now = sizeof(ce_signature);
		printf("String Physical Address = %lx \n", 
			*(unsigned long *)(dbuffer+d_now));
		
		d_now += sizeof(unsigned long);
		printf("Image Size = %ld [%lx]\n", 
			*(unsigned long *)(dbuffer+d_now), 
			*(unsigned long *)(dbuffer+d_now));
		
		d_now += sizeof(unsigned long);
		dbuffer_available -= d_now;			
		
		d_now = (unsigned long)get_x_header(dbuffer, d_now);
		firsttime = 0;
	}
	
	if (not_loadin == 0)
	{
		d_now = get_x_header(dbuffer, d_now);
	}
	
	while ( not_loadin > 0 )
	{
		/* dbuffer do not have enough data to loading, copy all */
#if LOAD_DEBUG
		printf("[0] not_loadin = [%ld], dbuffer_available = [%ld] \n", 
			not_loadin, dbuffer_available);
		printf("[0] d_now = [%ld] \n", d_now);
#endif
		
		if( dbuffer_available <= not_loadin)
		{
			this_write = dbuffer_available ;
			memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write );
			ce_curaddr += this_write;
			not_loadin -= this_write;
			
			/* reset index and available in the dbuffer */
			dbuffer_available = 0;
			d_now = 0;
#if LOAD_DEBUG
			printf("[1] not_loadin = [%ld], dbuffer_available = [%ld] \n", 
				not_loadin, dbuffer_available);
			printf("[1] d_now = [%ld], this_write = [%d] \n", 
				d_now, this_write);
#endif
				
			// get the next packet...
			return (0);
		}
			
		/* dbuffer have more data then loading ... , copy partital.... */
		else
		{
			this_write = not_loadin;
			memcpy(phys_to_virt(ce_curaddr), (dbuffer+d_now), this_write);
			ce_curaddr += this_write;
			not_loadin = 0;
			
			/* reset index and available in the dbuffer */
			dbuffer_available -= this_write;
			d_now += this_write;
#if LOAD_DEBUG
			printf("[2] not_loadin = [%ld], dbuffer_available = [%ld] \n", 
				not_loadin, dbuffer_available);
			printf("[2] d_now = [%ld], this_write = [%d] \n\n", 
				d_now, this_write);
#endif
			
			/* dbuffer not empty, proceed processing... */
			
			// don't have enough data to get_x_header..
			if ( dbuffer_available < (sizeof(unsigned long) * 3) )
			{
//				printf("we don't have enough data remaining to call get_x. \n");
				memcpy( (dbuffer+0), (dbuffer+d_now), dbuffer_available);
				return (0);
			}
			else
			{
#if LOAD_DEBUG				
				printf("with remaining data to call get_x \n");
				printf("dbuffer available = %ld , d_now = %ld\n", 
					dbuffer_available, d_now);
#endif					
				d_now = get_x_header(dbuffer, d_now);
			}
		}
	}
	return (0);
}

static int get_x_header(unsigned char *dbuffer, unsigned long now)
{
	X.addr = *(unsigned long *)(dbuffer + now);
	X.size = *(unsigned long *)(dbuffer + now + sizeof(unsigned long));
	X.checksum = *(unsigned long *)(dbuffer + now + sizeof(unsigned long)*2);

	if (X.addr == 0)
	{
		entry = X.size;
		done(1);
		printf("Entry Point Address = [%lx] \n", entry);
		jump_2ep();		
	}

	if (!prep_segment(X.addr, X.addr + X.size, X.addr + X.size, 0, 0)) {
		longjmp(restart_etherboot, -2);
	}

	ce_curaddr = X.addr;
	now += sizeof(unsigned long)*3;

	/* re-calculate dbuffer available... */
	dbuffer_available -= sizeof(unsigned long)*3;

	/* reset index of this section */
	not_loadin = X.size;
	
#if 1
	printf("\n");
	printf("\t Section Address = [%lx] \n", X.addr);
	printf("\t Size = %d [%lx]\n", X.size, X.size);
	printf("\t Checksum = %ld [%lx]\n", X.checksum, X.checksum);
#endif
#if LOAD_DEBUG
	printf("____________________________________________\n");
	printf("\t dbuffer_now = %ld \n", now);
	printf("\t dbuffer available = %ld \n", dbuffer_available);
	printf("\t not_loadin = %ld \n", not_loadin);
#endif

	return now;
}

static void jump_2ep()
{
	BootArgs.ucVideoMode = 1;
	BootArgs.ucComPort = 1;
	BootArgs.ucBaudDivisor = 1;
	BootArgs.ucPCIConfigType = 1;	// do not fill with 0
	
	BootArgs.dwSig = BOOTARG_SIG;
	BootArgs.dwLen = sizeof(BootArgs);
	
	if(BootArgs.ucVideoMode == 0)
	{
		BootArgs.cxDisplayScreen = 640;
		BootArgs.cyDisplayScreen = 480;
		BootArgs.cxPhysicalScreen = 640;
		BootArgs.cyPhysicalScreen = 480;
		BootArgs.bppScreen = 16;
		BootArgs.cbScanLineLength  = 1024;
		BootArgs.pvFlatFrameBuffer = 0x800a0000;	// ollie say 0x98000000
	}	
	else if(BootArgs.ucVideoMode != 0xFF)
	{
		BootArgs.cxDisplayScreen = 0;
		BootArgs.cyDisplayScreen = 0;
		BootArgs.cxPhysicalScreen = 0;
		BootArgs.cyPhysicalScreen = 0;
		BootArgs.bppScreen = 0;
		BootArgs.cbScanLineLength  = 0;
		BootArgs.pvFlatFrameBuffer = 0;	
	}

	ep = phys_to_virt(BOOT_ARG_PTR_LOCATION);
	*ep= virt_to_phys(&BootArgs);
	xstart32(entry);
}