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