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 void wait_for(u32 btn
)
54 if(PAD_ButtonsHeld(0) & btn
)
60 extern s32
__STM_Init();
61 extern void __exception_closeall();
62 extern s32
__IOS_ShutdownSubsystems();
64 /* code to establish a socket; originally from bzs@bu-cs.bu.edu
67 int establish(unsigned short portnum
) {
69 struct sockaddr_in sa
;
71 memset(&sa
, 0, sizeof(struct sockaddr_in
)); /* clear our address */
72 sa
.sin_family
= AF_INET
; /* this is our host address */
73 sa
.sin_port
= htons(portnum
); /* this is our port number */
74 sa
.sin_addr
.s_addr
= net_gethostip();
76 if ((s
= net_socket(AF_INET
, SOCK_STREAM
, 0)) < 0) /* create socket */
78 if (net_bind(s
,(struct sockaddr
*)&sa
,8) < 0) {
80 return(-1); /* bind address to socket */
82 net_listen(s
, 3); /* max # of queued connects */
86 // wait for a connection to occur on a socket created with establish()
88 int get_connection(int s
)
90 int t
; /* socket of connection */
91 struct sockaddr_in sa
;
93 sa
.sin_family
= AF_INET
;
95 t
= net_accept(s
,(struct sockaddr
*)&sa
, &buflen
);
96 printf("Incoming connection from %d.%d.%d.%d\n",
97 (sa
.sin_addr
.s_addr
>> 24) & 0xFF,
98 (sa
.sin_addr
.s_addr
>> 16) & 0xFF,
99 (sa
.sin_addr
.s_addr
>> 8) & 0xFF,
100 (sa
.sin_addr
.s_addr
) & 0xFF);
105 int read_data(int s
, /* connected socket */
106 char *buf
, /* pointer to the buffer */
107 int n
/* number of characters (bytes) we want */
109 { int bcount
; /* counts bytes read */
110 int br
; /* bytes read this pass */
114 while (bcount
< n
) { /* loop until full buffer */
115 if ((br
= net_read(s
,buf
,n
-bcount
)) > 0) {
116 bcount
+= br
; /* increment byte counter */
117 buf
+= br
; /* move buffer ptr for next read */
119 else if (br
< 0) /* signal an error to the caller */
122 // debug_printf("read_data(%d, %p, %d): \n", s, buf, n);
123 // printf("read_data(%d, %p, %d): %d\n", s, buf, n, bcount);
127 int write_data(int s
, char *buf
, int n
)
134 if ((br
= net_write(s
,buf
,n
-bcount
)) > 0) {
141 // debug_printf("write_data(%d, %p, %d): \n", s, buf, n);
142 // hexdump(buf, bcount);
146 int main(int argc
, char **argv
)
149 u32 res
, offset
, read
, size
, ip
;
157 switch(VIDEO_GetCurrentTvMode())
160 rmode
= &TVPal528IntDf
;
163 rmode
= &TVMpal480IntDf
;
166 rmode
= &TVNtsc480IntDf
;
170 xfb
= MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode
));
171 console_init(xfb
, 20, 20, rmode
->fbWidth
, rmode
->xfbHeight
, rmode
->fbWidth
* VI_DISPLAY_PIX_SZ
);
173 VIDEO_Configure(rmode
);
174 VIDEO_SetBlack(FALSE
);
175 VIDEO_SetNextFramebuffer(xfb
);
178 if(rmode
->viTVMode
& VI_NON_INTERLACE
)
183 printf("\n\nTCP ELF Loader\n");
184 printf("(c) 2008 Sven Peter\n");
185 printf("Based on bushing's title_listener.c and his networking code.\n");
186 printf("(c) 2008 bushing\n\n");
189 printf("Press A to continue.\n");
190 wait_for(PAD_BUTTON_A
);
192 printf("net_init(), please wait...\n");
196 printf("Opening socket on port 8080\n");
197 s32 listen
= establish(8080);
201 printf("establish() returned < 0.\n");
205 ip
= net_gethostip();
206 printf("fd = %d\n", listen
);
207 printf("You Wii's ip address is %d.%d.%d.%d\n", oct
[0], oct
[1], oct
[2], oct
[3]);
208 printf("Waiting for connection\n");
209 s32 client
= get_connection(listen
);
213 printf("client connected..\n");
215 if(read_data(client
, (char *)&size
, 4) < 0)
217 printf("read_data() error while reading filesize\n");
223 printf("size: %d\n", size
);
224 printf("reading data, please wait...\n");
227 while(offset
< size
&& (read
= read_data(client
, (char *)bfr
, (size
- offset
) > READ_SIZE
? READ_SIZE
: (size
- offset
))) > 0)
229 memcpy(data
+ offset
, bfr
, READ_SIZE
);
235 res
= valid_elf_image(data
);
238 printf("Invalid ELF image.\n");
239 printf("assuming DOL image. your wii will crash if this is just some random file...\n");
240 ep
= (void(*)())load_dol_image(data
, 1);
244 printf("Loading ELF image...\n");
245 ep
= (void(*)())load_elf_image(data
);
247 printf("entry point: 0x%08X\n", (unsigned int)ep
);
248 printf("shutting down...\n");
249 __IOS_ShutdownSubsystems();
250 _CPU_ISR_Disable(level
);
251 __exception_closeall();
252 printf("jumping to entry point now...\n\n\n\n");
254 _CPU_ISR_Restore(level
);
255 printf("this should not happen :/\n\n");
259 // never reached but fixes a gcc warning