tcploader: added possibility to deny connection and wait for new client
[svpe-wii.git] / tcploader / wii / main.c
blob92e4b3101c836ce94c23103e3f349ac489a5f054
1 /*-------------------------------------------------------------
3 tcploader -- a very small tcp elf loader for the wii
5 Copyright (C) 2008 Sven Peter
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any
9 damages arising from the use of this software.
11 Permission is granted to anyone to use this software for any
12 purpose, including commercial applications, and to alter it and
13 redistribute it freely, subject to the following restrictions:
15 1.The origin of this software must not be misrepresented; you
16 must not claim that you wrote the original software. If you use
17 this software in a product, an acknowledgment in the product
18 documentation would be appreciated but is not required.
20 2.Altered source versions must be plainly marked as such, and
21 must not be misrepresented as being the original software.
23 3.This notice may not be removed or altered from any source
24 distribution.
26 -------------------------------------------------------------*/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ogcsys.h>
32 #include <gccore.h>
33 #include <ogc/ipc.h>
34 #include <network.h>
36 #define READ_SIZE (1 << 10)
38 #include "asm.h"
39 #include "processor.h"
40 #include "elf.h"
41 #include "dol.h"
44 static void *xfb = NULL;
45 static GXRModeObj *rmode = NULL;
47 u8 *data = (u8 *)0x92000000;
49 static inline u32 wait_for(u32 btn)
51 u32 btns;
52 while(1)
54 PAD_ScanPads();
55 btns = PAD_ButtonsHeld(0);
56 if(btns & btn)
57 return btns;
58 VIDEO_WaitVSync();
63 extern s32 __STM_Init();
64 extern void __exception_closeall();
65 extern s32 __IOS_ShutdownSubsystems();
67 /* code to establish a socket; originally from bzs@bu-cs.bu.edu
70 int establish(unsigned short portnum) {
71 int s;
72 struct sockaddr_in sa;
74 memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
75 sa.sin_family= AF_INET; /* this is our host address */
76 sa.sin_port= htons(portnum); /* this is our port number */
77 sa.sin_addr.s_addr = net_gethostip();
78 sa.sin_len = 8;
79 if ((s= net_socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
80 return(-1);
81 if (net_bind(s,(struct sockaddr *)&sa,8) < 0) {
82 net_close(s);
83 return(-1); /* bind address to socket */
85 net_listen(s, 3); /* max # of queued connects */
86 return(s);
89 // wait for a connection to occur on a socket created with establish()
91 int get_connection(int s, struct sockaddr_in *sa)
93 int t; /* socket of connection */
94 // struct sockaddr_in sa;
95 sa->sin_len = 8;
96 sa->sin_family = AF_INET;
97 u32 buflen = 8;
98 t = net_accept(s,(struct sockaddr *)sa, &buflen);
99 printf("Incoming connection from %d.%d.%d.%d\n",
100 (sa->sin_addr.s_addr >> 24) & 0xFF,
101 (sa->sin_addr.s_addr >> 16) & 0xFF,
102 (sa->sin_addr.s_addr >> 8) & 0xFF,
103 (sa->sin_addr.s_addr) & 0xFF);
105 return t;
108 int read_data(int s, /* connected socket */
109 char *buf, /* pointer to the buffer */
110 int n /* number of characters (bytes) we want */
112 { int bcount; /* counts bytes read */
113 int br; /* bytes read this pass */
115 bcount= 0;
116 br= 0;
117 while (bcount < n) { /* loop until full buffer */
118 if ((br= net_read(s,buf,n-bcount)) > 0) {
119 bcount += br; /* increment byte counter */
120 buf += br; /* move buffer ptr for next read */
122 else if (br < 0) /* signal an error to the caller */
123 return br;
125 // debug_printf("read_data(%d, %p, %d): \n", s, buf, n);
126 // printf("read_data(%d, %p, %d): %d\n", s, buf, n, bcount);
127 return bcount;
130 int write_data(int s, char *buf, int n)
132 int bcount;
133 int br;
134 bcount = 0;
135 br = 0;
136 while(bcount < n) {
137 if ((br = net_write(s,buf,n-bcount)) > 0) {
138 bcount += br;
139 buf += br;
141 else if (br < 0)
142 return br;
144 // debug_printf("write_data(%d, %p, %d): \n", s, buf, n);
145 // hexdump(buf, bcount);
146 return (bcount);
149 int main(int argc, char **argv)
151 unsigned long level;
152 u32 res, offset, read, size, ip, client, btn;
153 u8 *oct = (u8 *)&ip;
154 u8 *bfr[READ_SIZE];
155 struct sockaddr_in addr;
156 void (*ep)();
158 VIDEO_Init();
159 PAD_Init();
161 switch(VIDEO_GetCurrentTvMode())
163 case VI_PAL:
164 rmode = &TVPal528IntDf;
165 break;
166 case VI_MPAL:
167 rmode = &TVMpal480IntDf;
168 default:
169 case VI_NTSC:
170 rmode = &TVNtsc480IntDf;
171 break;
174 xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
175 console_init(xfb, 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * VI_DISPLAY_PIX_SZ);
177 VIDEO_Configure(rmode);
178 VIDEO_SetBlack(FALSE);
179 VIDEO_SetNextFramebuffer(xfb);
180 VIDEO_Flush();
181 VIDEO_WaitVSync();
182 if(rmode->viTVMode & VI_NON_INTERLACE)
183 VIDEO_WaitVSync();
185 __STM_Init();
187 printf("\n\nTCP ELF Loader\n");
188 printf("(c) 2008 Sven Peter\n");
189 printf("Based on bushing's title_listener.c and his networking code.\n");
190 printf("(c) 2008 bushing\n\n");
192 redo:
193 printf("Press A to continue.\n");
194 wait_for(PAD_BUTTON_A);
196 printf("net_init(), please wait...\n");
197 net_init();
200 printf("Opening socket on port 8080\n");
201 s32 listen = establish(8080);
203 if(listen < 0)
205 printf("establish() returned < 0.\n");
206 goto redo;
209 ip = net_gethostip();
210 printf("fd = %d\n", listen);
211 printf("You Wii's ip address is %d.%d.%d.%d\n", oct[0], oct[1], oct[2], oct[3]);
213 while(1)
215 printf("Waiting for connection\n");
216 client = get_connection(listen, &addr);
218 if(client > 0)
220 printf("client connected..\n");
221 printf("Please check the IP address and press A to continue and Z to abort\n");
222 btn = wait_for(PAD_BUTTON_A | PAD_TRIGGER_Z);
223 if(btn & PAD_TRIGGER_Z)
225 net_close(client);
226 continue;
229 if(((addr.sin_addr.s_addr >> 24) & 0xFF) != oct[0] || ((addr.sin_addr.s_addr >> 16) & 0xFF) != oct[1])
231 printf("WARNING: the client is not connecting from your local network.\n");
232 printf("Please check if you really want to run a file from this IP as it\n");
233 printf("may be something that bricks your wii from someone you don't even know!!\n");
234 printf("Press Z if you really want to continue!\n");
235 printf("Press A to deny the connection and wait for a new client\n");
236 btn = wait_for(PAD_TRIGGER_Z | PAD_BUTTON_A);
237 if(btn & PAD_BUTTON_A)
239 net_close(client);
240 continue;
244 if(read_data(client, (char *)&size, 4) < 0)
246 printf("read_data() error while reading filesize\n");
247 net_close(client);
248 net_close(listen);
249 goto redo;
252 printf("size: %d\n", size);
253 printf("reading data, please wait...\n");
255 offset = 0;
256 while(offset < size && (read = read_data(client, (char *)bfr, (size - offset) > READ_SIZE ? READ_SIZE : (size - offset))) > 0)
258 memcpy(data + offset, bfr, READ_SIZE);
259 offset += read;
261 net_close(client);
262 net_close(listen);
264 res = valid_elf_image(data);
265 if(res != 1)
267 printf("Invalid ELF image.\n");
268 printf("assuming DOL image. your wii will crash if this is just some random file...\n");
269 ep = (void(*)())load_dol_image(data, 1);
271 else
273 printf("Loading ELF image...\n");
274 ep = (void(*)())load_elf_image(data);
276 printf("entry point: 0x%08X\n", (unsigned int)ep);
277 printf("shutting down...\n");
278 __IOS_ShutdownSubsystems();
279 _CPU_ISR_Disable(level);
280 __exception_closeall();
281 printf("jumping to entry point now...\n\n\n\n");
282 ep();
283 _CPU_ISR_Restore(level);
284 printf("this should not happen :/\n\n");
285 goto redo;
289 // never reached but fixes a gcc warning
290 return 0;