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.2 2008/06/13 04:43:37 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_A     "/aD.rso"
25 #define MODULE_B     "/bD.rso"
26 #define STATIC_RSO   "/staticD.sel"
27 #else
28 #define MODULE_A     "/a.rso"
29 #define MODULE_B     "/b.rso"
30 #define STATIC_RSO   "/static.sel"
31 #endif
32 
33 void _unresolved();
34 
35 /*---------------------------------------------------------------------------*
36    Load
37  *---------------------------------------------------------------------------*/
38 // Load and link the specified module
RsoLoadFixed(char * moduleName,RSOFixedLevel i_fixed_level)39 static RSOObjectHeader* RsoLoadFixed(char* moduleName,RSOFixedLevel i_fixed_level)
40 {
41     DVDFileInfo     fileInfo;
42     s32             length;
43     BOOL            result;
44     RSOObjectHeader* module;
45     u8*             bss;
46     u32             fixed_size;
47     u32             new_arenaLo;
48     u32             old_arenaLo;
49     result = DVDOpen(moduleName, &fileInfo);
50     if (!result)
51         return NULL;
52     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
53     module = OSAllocFromArenaLo((u32) length, 32);
54     result = DVDRead(&fileInfo, module, length, 0);
55     if (!result)
56         return NULL;
57     DVDClose(&fileInfo);
58     //
59     fixed_size = RSOGetFixedSize(module,i_fixed_level);
60 
61     // 0 indicates failure
62     ASSERT(fixed_size);
63     //
64     bss = (u8 *)((u32)module + fixed_size);
65     //  32-byte alignment
66     bss = (u8*) OSRoundUp32B(bss);
67 
68     new_arenaLo = ((u32)bss + (u32)module->bssSize);
69     new_arenaLo = OSRoundUp32B(new_arenaLo);
70     old_arenaLo = (u32)OSGetMEM1ArenaLo();
71     //
72     if (module->bssSize > 0) {
73         if(old_arenaLo < new_arenaLo) {
74             // Increase the allocated region
75             // When increasing, increase before executing RSOLocateObjectFixed
76             OSSetMEM1ArenaLo((void*)new_arenaLo);
77         }
78     } else {
79         bss = NULL;
80     }
81     //
82     RSOLinkListFixed(module,bss,i_fixed_level);
83     // When decreasing the memory area, do so after executing RSOLocateObjectFixed
84     if(bss == NULL || old_arenaLo > new_arenaLo) {
85         OSSetMEM1ArenaLo((void*)new_arenaLo);
86     }
87     return module;
88 }
89 
90 // Load and link the static module
StaticRsoLoad(char * moduleName)91 static RSOObjectHeader* StaticRsoLoad(char* moduleName)
92 {
93     DVDFileInfo     fileInfo;
94     s32             length;
95     BOOL            result;
96     RSOObjectHeader* module;
97 
98     result = DVDOpen(moduleName, &fileInfo);
99     if (!result)
100         return NULL;
101     length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo));
102     module = OSAllocFromArenaLo((u32) length, 32);
103     result = DVDRead(&fileInfo, module, length, 0);
104     if (!result)
105         return NULL;
106     DVDClose(&fileInfo);
107 
108     RSOListInit(module);
109 
110     return module;
111 }
112 
113 //
_unresolved()114 void _unresolved()
115 {
116     OSReport("_unresolved func.\n");
117 }
118 
119 
120 // Functions and variables we want to access
121 void (*MainA)();
122 void (*IsAThere)();
123 int  (*g_intA);
124 
125 //
126 static RSOExportFuncTable exp_tbl[] =
127 {
128     {"MainA",   (u32 *)&MainA},
129     {"IsAThere",(u32 *)&IsAThere},
130     {"g_intA",  (u32 *)&g_intA},
131 };
132 
133 //
RSOResolvedModuleA(const RSOObjectHeader * module)134 static void RSOResolvedModuleA(const RSOObjectHeader* module)
135 {
136     int i;
137     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
138         *(exp_tbl[i].symbol_ptr) =
139             (u32)RSOFindExportSymbolAddr(module, exp_tbl[i].symbol_name);
140 
141     }
142 }
143 
144 //
145 //
RSOUnresolvedModuleA(void)146 static void RSOUnresolvedModuleA(void)
147 {
148     int i;
149     for(i = 0; i < sizeof(exp_tbl)/sizeof(RSOExportFuncTable); i++) {
150         *(exp_tbl[i].symbol_ptr) = (u32)_unresolved;
151     }
152 }
153 
154 
155 //Main
main(void)156 int main(void)
157 {
158     RSOObjectHeader* staticRso;
159     RSOObjectHeader* moduleA;
160     RSOObjectHeader* moduleB;
161 
162     // Generate weak symbol 'InlineFunc'
163     DVDInit();
164 
165     //Read
166     // Load static rso file
167     OSReport("Loading static rso...\n");
168     staticRso = StaticRsoLoad(STATIC_RSO);
169     if (!staticRso)
170         return 1;
171 
172     // Load and link module A
173     OSReport("Linking module A...\n");
174     moduleA = RsoLoadFixed(MODULE_A,RSO_FL_INTERNAL);
175     if (!moduleA) {
176         return 1;
177     }
178 
179     // Load and link module B
180     OSReport("Linking module B...\n");
181     moduleB = RsoLoadFixed(MODULE_B,RSO_FL_INTERNAL);
182     if (!moduleB) {
183         return 1;
184     }
185 
186     //Check whether everything has been resolved
187     if (RSOIsImportSymbolResolvedAll(moduleA))
188     {
189         OSReport("moduleA's ImportSymbol is resolved all.\n");
190     }
191     if (RSOIsImportSymbolResolvedAll(moduleB))
192     {
193         OSReport("moduleB's ImportSymbol is resolved all.\n");
194     }
195 
196     // Since A and B are mutually linked, resolve both and then call prolog.
197     OSReport("\nA prolog()\n");
198     ((u32 (*)(void)) moduleA->prolog)();
199     OSReport("\nB prolog()\n");
200     ((u32 (*)(void)) moduleB->prolog)();
201 
202     //
203     RSOResolvedModuleA(moduleA);
204     //
205     OSReport("MainA = %x\n",MainA);
206     OSReport("g_intA = %x\n",g_intA);
207 
208     MainA();
209     OSReport("g_intA = %d\n", *g_intA);
210     *g_intA += 5;
211     OSReport("g_intA + 5 = %d\n", *g_intA);
212     MainA();
213 
214     //
215     OSReport("\nA epilog()\n");
216     ((u32 (*)(void)) moduleA->epilog)();
217     RSOUnresolvedModuleA();
218     //
219     OSReport("\nB epilog()\n");
220     ((u32 (*)(void)) moduleB->epilog)();
221 
222     // Since A and B mutually refer to each other, unlink after the epilog for both
223     RSOUnLinkList(moduleA);
224     RSOUnLinkList(moduleB);
225 
226     //
227     OSReport("\nRSOLink finish all!\n");
228 
229     return 0;
230 }
231