1 /*---------------------------------------------------------------------------*
2   Project:  rsodemo
3   File:     static.c
4 
5   Copyright 2006 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   @version $Id: static.c,v 1.4 2008/06/16 02:47:48 mitu Exp $
14 
15   $NoKeywords: $
16  *---------------------------------------------------------------------------*/
17 
18 #include <revolution.h>
19 
20 #include <revolution/rso.h>
21 
22 
23 #ifdef _DEBUG
24 #define MODULE_G     "/gD.rso"
25 #define MODULE_H     "/hD.rso"
26 #define STATIC_RSO   "/staticD.sel"
27 #else
28 #define MODULE_G     "/g.rso"
29 #define MODULE_H     "/h.rso"
30 #define STATIC_RSO   "/static.sel"
31 #endif
32 
33 //
34 void _unresolved();
35 
36 /*---------------------------------------------------------------------------*
37    RsoLinkFar
38  *---------------------------------------------------------------------------*/
LinkFar(RSOObjectHeader * i_rsoImp,RSOObjectHeader * i_rsoExp)39 static u32 *LinkFar(RSOObjectHeader *i_rsoImp,RSOObjectHeader *i_rsoExp)
40 {
41     int a_size = RSOGetFarCodeSize(i_rsoImp,i_rsoExp);
42     u32 *a_buff;
43 
44     //
45     if(a_size == 0) {
46         // not needed
47         return NULL;
48     }
49     //
50     a_buff = OSAllocFromArenaHi((u32)a_size,4);
51     //
52     if(RSOLinkFar(i_rsoImp,i_rsoExp,a_buff) == -1)
53     {
54         OSHalt("i_rsoImp and a_buff are too away.\n");
55     }
56     //
57 #if 0
58     {
59         int i,j;
60         OSReport("buff = %p\n",a_buff);
61         for(i = 0,j = 0;
62             i < a_size;
63             i+=16,j+=4) {
64             OSReport("%p\n%p\n%p\n%p\n",
65                      a_buff[j],a_buff[j+1],a_buff[j+2],a_buff[j+3]);
66         }
67     }
68 #endif
69     //
70     return a_buff;
71 }
LinkFarMem2(RSOObjectHeader * i_rsoImp,RSOObjectHeader * i_rsoExp)72 static u32 *LinkFarMem2(RSOObjectHeader *i_rsoImp,RSOObjectHeader *i_rsoExp)
73 {
74     int a_size = RSOGetFarCodeSize(i_rsoImp,i_rsoExp);
75     u32 *a_buff;
76 
77     //
78     if(a_size == 0) {
79         // not needed
80         return NULL;
81     }
82     //
83     a_buff = OSAllocFromMEM2ArenaLo((u32)a_size,4);
84     //
85     if(RSOLinkFar(i_rsoImp,i_rsoExp,a_buff) == -1)
86     {
87         OSHalt("i_rsoImp and a_buff are too away.\n");
88     }
89     //
90 #if 0
91     {
92         int i,j;
93         OSReport("buff = %p\n",a_buff);
94         for(i = 0,j = 0;
95             i < a_size;
96             i+=16,j+=4) {
97             OSReport("%p\n%p\n%p\n%p\n",
98                      a_buff[j],a_buff[j+1],a_buff[j+2],a_buff[j+3]);
99         }
100     }
101 #endif
102     //
103     return a_buff;
104 }
105 
106 /*---------------------------------------------------------------------------*
107    Load
108  *---------------------------------------------------------------------------*/
109 // Load and link the specified module
RsoLoad(char * moduleName)110 static RSOObjectHeader* RsoLoad(char* moduleName)
111 {
112     DVDFileInfo     fileInfo;
113     s32             length;
114     BOOL            result;
115     RSOObjectHeader* module;
116     u8*             bss;
117 
118     result = DVDOpen(moduleName, &fileInfo);
119     if (!result)
120         return NULL;
121     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
122     module = OSAllocFromArenaLo((u32) length, 32);
123     result = DVDRead(&fileInfo, module, length, 0);
124     if (!result)
125         return NULL;
126     DVDClose(&fileInfo);
127 
128     if (module->bssSize > 0)
129     {
130         bss = OSAllocFromArenaLo(module->bssSize, 32); // Alloc bss area
131     }
132     RSOLinkList(module, bss);
133 
134     return module;
135 }
136 
137 //
RsoLoadMem2(char * moduleName)138 static RSOObjectHeader* RsoLoadMem2(char* moduleName)
139 {
140     DVDFileInfo     fileInfo;
141     s32             length;
142     BOOL            result;
143     RSOObjectHeader* module;
144     u8*             bss;
145 
146     result = DVDOpen(moduleName, &fileInfo);
147     if (!result)
148         return NULL;
149     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
150     module = OSAllocFromMEM2ArenaLo((u32) length, 32);
151     result = DVDRead(&fileInfo, module, length, 0);
152     if (!result)
153         return NULL;
154     DVDClose(&fileInfo);
155 
156     if (module->bssSize > 0)
157     {
158         bss = OSAllocFromMEM2ArenaLo(module->bssSize, 32); // Alloc bss area
159     }
160     RSOLinkList(module, bss);
161 
162     return module;
163 }
164 
165 // Load and link the static module
StaticRsoLoad(char * moduleName)166 static RSOObjectHeader* StaticRsoLoad(char* moduleName)
167 {
168     DVDFileInfo     fileInfo;
169     s32             length;
170     BOOL            result;
171     RSOObjectHeader* module;
172 
173     result = DVDOpen(moduleName, &fileInfo);
174     if (!result)
175         return NULL;
176     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
177     module = OSAllocFromArenaLo((u32) length, 32);
178     result = DVDRead(&fileInfo, module, length, 0);
179     if (!result)
180         return NULL;
181     DVDClose(&fileInfo);
182 
183     RSOListInit(module);
184 
185     return module;
186 }
187 
188 //
_unresolved()189 void _unresolved()
190 {
191     OSReport("_unresolved func.\n");
192 }
193 
194 
195 // Functions and variables we want to access
196 void (*MainG)();
197 
198 //
199 static RSOExportFuncTable exp_tbl[] =
200 {
201     {"MainG",   (u32 *)&MainG},
202 };
203 //
RSOResolvedModuleG(const RSOObjectHeader * module)204 static void RSOResolvedModuleG(const RSOObjectHeader* module)
205 {
206     int i;
207     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
208         *(exp_tbl[i].symbol_ptr) =
209             (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name);
210 
211     }
212 }
213 
214 //
RSOUnresolvedModuleG(void)215 static void RSOUnresolvedModuleG(void)
216 {
217     int i;
218     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
219         *(exp_tbl[i].symbol_ptr) = (u32)_unresolved;
220     }
221 }
222 
223 //Main
main(void)224 int main(void)
225 {
226     RSOObjectHeader* staticRso;
227     RSOObjectHeader* moduleG;
228     RSOObjectHeader* moduleH;
229     u32*             buff_gh;      // Buffer necessary when H is LinkFar-ed to G
230     u32*             buff_hg;      // Buffer necessary when G is LinkFar-ed to H
231     u32*             buff_sg;      // Buffer necessary when G is LinkFar-ed to H
232 
233     OSEnableCodeExecOnMEM2Lo8MB();
234 
235     // Generate weak symbol 'InlineFunc'
236     DVDInit();
237 
238     //Read
239     // Load static rso file
240     OSReport("Loading static rso...\n");
241     staticRso = StaticRsoLoad(STATIC_RSO);
242     if (!staticRso)
243         return 1;
244 
245     // Load and link module G
246     OSReport("Linking module G...\n");
247     moduleG = RsoLoadMem2(MODULE_G);
248     if (!moduleG) {
249         return 1;
250     }
251 
252     // Load and link module H
253     OSReport("Linking module H...\n");
254     moduleH = RsoLoad(MODULE_H);
255     if (!moduleH) {
256         return 1;
257     }
258 
259     // When linking from H, get region from MEM1 where H is located
260     buff_gh = LinkFar(moduleH,moduleG);
261     // When linking from G, get region from MEM2 where G is located
262     buff_hg = LinkFarMem2(moduleG,moduleH);
263     buff_sg = LinkFarMem2(moduleG,staticRso);
264 
265     //Check whether everything has been resolved
266     if (RSOIsImportSymbolResolvedAll(moduleG))
267     {
268         OSReport("moduleG's ImportSymbol is resolved all.\n");
269     }
270     if (RSOIsImportSymbolResolvedAll(moduleH))
271     {
272         OSReport("moduleH's ImportSymbol is resolved all.\n");
273     }
274     //
275     OSReport("\nG prolog()\n");
276     ((u32 (*)(void)) moduleG->prolog)();
277     RSOResolvedModuleG(moduleG);
278     //
279     OSReport("\nH prolog()\n");
280     ((u32 (*)(void)) moduleH->prolog)();
281     //
282     OSReport("\ncall MainG = %p\n",MainG);
283     //
284     MainG();
285 
286     //
287     OSReport("\nG epilog()\n");
288     ((u32 (*)(void)) moduleG->epilog)();
289     RSOUnresolvedModuleG();
290     //
291     OSReport("\nH epilog()\n");
292     ((u32 (*)(void)) moduleH->epilog)();
293     //
294     RSOUnLinkList(moduleG);
295     RSOUnLinkList(moduleH);
296     //
297     OSReport("\nRSOLink finish all!\n");
298     // Release buff_gh and other memory after RSOUnLinkList.
299 
300     return 0;
301 }
302 
303