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
26 -------------------------------------------------------------*/
36 #define READ_SIZE (1 << 10)
39 #include "processor.h"
44 static void *xfb
= NULL
;
45 static GXRModeObj
*rmode
= NULL
;
47 u8
*data
= (u8
*)0x92000000;
49 static inline u32
wait_for(u32 btn
)
55 btns
= PAD_ButtonsHeld(0);
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
) {
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();
79 if ((s
= net_socket(AF_INET
, SOCK_STREAM
, 0)) < 0) /* create socket */
81 if (net_bind(s
,(struct sockaddr
*)&sa
,8) < 0) {
83 return(-1); /* bind address to socket */
85 net_listen(s
, 3); /* max # of queued connects */
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;
96 sa
->sin_family
= AF_INET
;
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);
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 */
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 */
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);
130 int write_data(int s
, char *buf
, int n
)
137 if ((br
= net_write(s
,buf
,n
-bcount
)) > 0) {
144 // debug_printf("write_data(%d, %p, %d): \n", s, buf, n);
145 // hexdump(buf, bcount);
149 int main(int argc
, char **argv
)
152 u32 res
, offset
, read
, size
, ip
, client
, btn
;
155 struct sockaddr_in addr
;
161 switch(VIDEO_GetCurrentTvMode())
164 rmode
= &TVPal528IntDf
;
167 rmode
= &TVMpal480IntDf
;
170 rmode
= &TVNtsc480Prog
;
174 rmode
= &TVNtsc480IntDf
;
178 xfb
= MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode
));
179 console_init(xfb
, 20, 20, rmode
->fbWidth
, rmode
->xfbHeight
, rmode
->fbWidth
* VI_DISPLAY_PIX_SZ
);
181 VIDEO_Configure(rmode
);
182 VIDEO_SetBlack(FALSE
);
183 VIDEO_SetNextFramebuffer(xfb
);
186 if(rmode
->viTVMode
& VI_NON_INTERLACE
)
191 printf("\n\n TCP ELF Loader\n");
192 printf(" (c) 2008 Sven Peter\n");
193 printf(" Based on bushing's title_listener.c and his networking code.\n");
194 printf(" (c) 2008 bushing\n\n");
197 printf(" Press A to continue.\n");
198 wait_for(PAD_BUTTON_A
);
200 printf(" net_init(), please wait...\n");
204 printf(" Opening socket on port 8080\n");
205 s32 listen
= establish(8080);
209 printf(" establish() returned < 0.\n");
213 ip
= net_gethostip();
214 printf(" fd = %d\n", listen
);
215 printf(" You Wii's ip address is %d.%d.%d.%d\n", oct
[0], oct
[1], oct
[2], oct
[3]);
219 printf(" Waiting for connection\n");
220 client
= get_connection(listen
, &addr
);
224 printf(" client connected..\n");
225 printf(" Please check the IP address and press A to continue and Z to abort\n");
226 btn
= wait_for(PAD_BUTTON_A
| PAD_TRIGGER_Z
);
227 if(btn
& PAD_TRIGGER_Z
)
233 if(((addr
.sin_addr
.s_addr
>> 24) & 0xFF) != oct
[0] || ((addr
.sin_addr
.s_addr
>> 16) & 0xFF) != oct
[1])
235 printf(" WARNING: the client is not connecting from your local network.\n");
236 printf(" Please check if you really want to run a file from this IP as it\n");
237 printf(" may be something that bricks your wii from someone you don't even know!!\n");
238 printf(" Press Z if you really want to continue!\n");
239 printf(" Press A to deny the connection and wait for a new client\n");
240 btn
= wait_for(PAD_TRIGGER_Z
| PAD_BUTTON_A
);
241 if(btn
& PAD_BUTTON_A
)
248 if(read_data(client
, (char *)&size
, 4) < 0)
250 printf(" read_data() error while reading filesize\n");
256 printf(" size: %d\n", size
);
257 printf(" reading data, please wait...\n");
260 while(offset
< size
&& (read
= read_data(client
, (char *)bfr
, (size
- offset
) > READ_SIZE
? READ_SIZE
: (size
- offset
))) > 0)
262 memcpy(data
+ offset
, bfr
, READ_SIZE
);
268 res
= valid_elf_image(data
);
271 printf(" Invalid ELF image.\n");
272 printf(" assuming DOL image. your wii will crash if this is just some random file...\n");
273 ep
= (void(*)())load_dol_image(data
, 1);
277 printf(" Loading ELF image...\n");
278 ep
= (void(*)())load_elf_image(data
);
280 printf(" entry point: 0x%08X\n", (unsigned int)ep
);
281 printf(" shutting down...\n");
282 __IOS_ShutdownSubsystems();
283 _CPU_ISR_Disable(level
);
284 __exception_closeall();
285 printf(" jumping to entry point now...\n\n\n\n");
287 _CPU_ISR_Restore(level
);
288 printf(" this should not happen :/\n\n");
293 // never reached but fixes a gcc warning