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
= &TVNtsc480IntDf
;
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
);
182 if(rmode
->viTVMode
& VI_NON_INTERLACE
)
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");
193 printf("Press A to continue.\n");
194 wait_for(PAD_BUTTON_A
);
196 printf("net_init(), please wait...\n");
200 printf("Opening socket on port 8080\n");
201 s32 listen
= establish(8080);
205 printf("establish() returned < 0.\n");
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]);
215 printf("Waiting for connection\n");
216 client
= get_connection(listen
, &addr
);
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
)
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
)
244 if(read_data(client
, (char *)&size
, 4) < 0)
246 printf("read_data() error while reading filesize\n");
252 printf("size: %d\n", size
);
253 printf("reading data, please wait...\n");
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
);
264 res
= valid_elf_image(data
);
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);
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");
283 _CPU_ISR_Restore(level
);
284 printf("this should not happen :/\n\n");
289 // never reached but fixes a gcc warning