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