1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> 4<LINK rel="stylesheet" type="text/css" href="../CSS/revolution.css"> 5<base target="main"> 6<title>RSO Function Introduction</title> 7</head> 8 9<body> 10 11<h1>RSO API</h1> 12 13<h2>Introduction</h2> 14<p> 15The RSO Library is a relocatable module system.<BR><BR> It can use main memory efficiently by dynamically reading and deallocating program modules in the game application.<BR> In this library, unlike the dynamic link library of other operating systems, the game application is responsible for main memory allocation and deallocation and loading modules from the disk.<BR> <BR>The RSO library consists of one static module (the <CODE>.elf</CODE> file), one static information module (the <CODE>.sel</CODE> file), and multiple dynamic (that is, relocatable) modules (the <CODE>.rso</CODE> files). After the boot ROM loads the static module of the program, the static module controls the memory location of the dynamic module. The static module is built as a normal <CODE>.elf</CODE> file. The static module contains common functions and common variables referenced by the dynamic modules.<BR><BR>Dynamic (relocatable) modules can call functions and refer to the variables defined in static modules. In addition, dynamic modules can call functions and refer to variables in other dynamic modules loaded into main memory. Referencing across modules is resolved by directly revising the code and data sections of a module when it is loaded.<BR><BR> Functions and variables of the dynamic (relocatable) module can be accessed by specifying the symbol name from the static module.<BR> Accordingly, the program must be aware of the dynamic modules that it uses, unlike when calling functions within static modules.<BR> <BR>A dynamic module (RSO) application is written in the same manner as the main C/C++ code, except that the dynamic module is built from a partially linked <CODE>.elf</CODE> file (PLF). A PLF file contains unresolved external symbols and debug information. The <CODE><a href="./tools/makerso.html">makerso</a></CODE> tool, provided with the Revolution SDK, will convert a PLF file into a dynamic module file used exclusively by the Wii console. These Wii-specific dynamic modules include, in addition to the standard application code and data section, a relocation instruction list, import information, and export information.<BR><BR> Import information is used to reference external elements, and export information allows referencing by external elements.<BR> 16 17<h2>Differences from REL</h2> 18<H3>Advantages</H3> 19<UL> 20<LI>The dynamic module functions and variables can be accessed from the static module by specifying symbol names. 21<LI>As long as there are <CODE>.rso</CODE> files, the library can run, even if all the dynamic module <CODE>.plf</CODE> files have not been prepared first. (For example, you can run RSO files that have been pre-stored in NAND memory or other areas and update dynamic modules through downloading, etc.) 22<LI>The user can specify links. 23</UL> 24<H3>Drawbacks</H3> 25<UL> 26<LI>Because the module includes symbol information, it is larger than REL. (By approximately the same number of bytes as the character count.) 27<LI>The user must manage access to dynamic modules from static modules. 28<LI>Because dynamic modules can be accessed from static modules, it is harder to delete code by optimizing compilation. 29<LI>Because resolution is done using symbol names, more processing is required for linking than with REL. 30</UL> 31<H3>Procedural Differences</H3> 32<UL> 33<LI>The static module information (the <CODE>.sel</CODE> file) is required for initializing the link list. 34</UL> 35 36<h2>Making Relocatable Modules</h2> 37<p> 38<H3>1. Create the partially linked ELF files.</H3> 39<P>The RSO library uses the static linker <B>partial link</B> option. Each dynamic (relocatable) module is made from a separate set of partially linked files. Using the partial link option (<CODE>-r</CODE>), the linker can create an <CODE>.elf</CODE> file that includes unresolved external reference symbols. The unresolved symbols of the dynamic module are resolved when the application is run.</P> 40<P>Three functions can be defined for a dynamic module: <CODE>_prolog</CODE>, <CODE>_epilog</CODE>, and <CODE>_unresolved</CODE>. <CODE>_prolog</CODE> and <CODE>_epilog</CODE> can be called from static modules or from other dynamic modules loaded in main memory. <CODE>_unresolved</CODE> is automatically called when the module makes a function call to an external function that has not been linked into the main memory.</P> 41<p>The linker command file for a dynamic module will be the result of adding <CODE>FORCEFILES</CODE> and <CODE>FORCEACTIVE</CODE> to the <CODE><revolution/eppc.$(PLATFORM).lcf></CODE> file. <CODE>FORCEFILES</CODE> includes the target files, and <CODE>FORCEACTIVE</CODE> includes the <CODE>__global_destructor_chain</CODE>. 42</p> 43<p>In the sample this file is output in <CODE>.plf</CODE> format. 44</p> 45<P><STRONG><EM>Note: </EM></STRONG> A relocatable module cannot have a small data section. The small data section base registers (r2 and r13) are reserved for the static module. To prevent the compiler from generating small data sections, specify the compiler options <CODE>-sdata 0 -sdata2 0</CODE> when compiling the relocatable modules.</P> 46 47<H3>2. Create a dynamic module file from the partially linked ELF files.</H3> 48<p> 49Run the <CODE><a href="./tools/makerso.html">makerso</a></CODE> tool to create a dynamic module file (<code>.rso</code>) from a partially linked <CODE>.plf</CODE> file. 50</p> 51<TABLE border="1" width="95%"> 52 <TBODY> 53 <TR> 54 <TD width="100%"> 55 <PRE><CODE> 56% makerso.exe a.plf -a</CODE></PRE> 57 </TD> 58 </TR> 59 </TBODY> 60</TABLE> 61 62<H3>3. Create a static module linker command file and symbol list from all dynamic module files.</H3> 63<p>Run the <CODE><a href="./tools/makelcf.html">makelcf</a></CODE> tool to create a static module linker command file and symbol list from all dynamic module files.<br>The linker command file is generated by adding the <CODE>FORCEACTIVE</CODE> list to the <CODE><revolution/eppc.$(PLATFORM).lcf></CODE> file.<br> 64</p> 65<p>The following shows how to generate a static module linker command file as <CODE>static.lcf</CODE> and a symbol list as <CODE>symbol.lst</CODE>. 66</p> 67<TABLE border="1" width="95%"> 68 <TBODY> 69 <TR> 70 <TD width="100%"> 71 <PRE><CODE> 72% makelcf.exe -o static.lcf -s symbol.lst -t eppc.RVL.lcf a.rso b.rso 73</CODE></PRE> 74 </TD> 75 </TR> 76 </TBODY> 77</TABLE> 78<H3>4. Build the program static modules.</H3> 79<p>Link the static modules of the program with the linker command file generated in the previous section. Link all static libraries to the static module. 80</p> 81</p> 82<H3>5. Generate static module information from the static ELF file.</H3> 83<p>Use the <CODE><a href="./tools/makerso.html">makerso</a></CODE> tool to create static module information from the static <CODE>.elf</CODE> file and the symbol list generated in section 3. 84</p> 85<p> 86The following shows how to generate a static module information as a <CODE>static.sel</CODE> file. 87</p> 88<TABLE border="1" width="95%"> 89 <TBODY> 90 <TR> 91 <TD width="100%"> 92 <PRE><CODE> 93% makerso.exe static.elf -e symbol.lst 94</CODE></PRE> 95 </TD> 96 </TR> 97 </TBODY> 98</TABLE> 99 100</p> 101 102<h2>Using Dynamic Modules</h2> 103<p><B>Note:</B> The game application performs memory allocation and deallocation for loading dynamic modules and loading dynamic modules from game discs.<br>The dynamic module loaded into main memory has type <code>RSOObjectHeader</code> data, followed by the module code and data sections.<br>Static module information has the same data structure as dynamic modules, but without the code, the import information, or the internal processing information. 104</p> 105<H3>1. Loading Individual Modules</H3> 106<p>The following is an example of loading modules. 107</p> 108<TABLE border="1" width="95%"> 109 <TBODY> 110 <TR> 111 <TD width="100%"> 112 <PRE><CODE> 113DVDFileInfo fileInfo; 114s32 length; 115RSOObjectHeader* module; 116 117DVDOpen("a.rso", &fileInfo); 118length = (s32) OSRoundUp32B(DVDGetLength(&fileInfo)); 119module = OSAllocFromArenaLo((u32) length, 32); 120DVDRead(&fileInfo, module, length, 0); 121DVDClose(&fileInfo);</CODE></PRE> 122 </TD> 123 </TR> 124 </TBODY> 125</TABLE> 126<H3>2. Initializing the Linked List</H3> 127<p>Use <code><a href="./RSOListInit.html">RSOListInit</a></code> to initialize the linked list.<br>Static module information is set at this time.<br>The static module information is used to obtain the address of a function or variable inside the static module when it is referenced by a dynamic module. 128</p> 129<TABLE border="1" width="95%"> 130 <TBODY> 131 <TR> 132 <TD width="100%"> 133 <PRE><CODE> 134RSOListInit(staticModule);</CODE></PRE> 135 </TD> 136 </TR> 137 </TBODY> 138</TABLE> 139<H3>3. Registering the Dynamic Module to the Linked List</H3> 140<p> 141Use <code><a href="./RSOLinkList.html">RSOLinkList</a></code> to link the dynamic module.<br>The <code><I>bss</I></code> argument is a pointer to the section used as a BSS section (a section initialized with 0s). It is allocated and specified by the programmer.<br>The required BSS section size is given by <CODE>RSOObjectHeader.bssSize</CODE>.<br>After linking a module, the game is given the choice to call the <code>prolog</code> function (a member variable of the <code>RSOObjectHeader</code> structure). 142</p> 143<TABLE border="1" width="95%"> 144 <TBODY> 145 <TR> 146 <TD width="100%"> 147 <PRE><CODE> 148void *bss; 149// Allocate BSS region 150bss = OSAllocFromArenaLo(module->bssSize, 32); 151RSOLinkList(module, bss); 152((u32 (*)(void)) module->prolog)();</CODE></PRE> 153 </TD> 154 </TR> 155 </TBODY> 156</TABLE> 157<H3>4. Removing the Dynamic Module from the Linked List</H3> 158<p> 159If the loaded module becomes unnecessary, call <code><a href="./RSOUnLinkList.html">RSOUnLinkList</a></code> to free the memory space for another purpose.<br>Immediately before unlinking a module, the game is given the choice to call the <code>epilog</code> function (a member variable of the <code>RSOObjectHeader</code> structure). 160</p> 161<TABLE border="1" width="95%"> 162 <TBODY> 163 <TR> 164 <TD width="100%"> 165 <PRE><CODE> 166((void (*)(void)) module->epilog)(); 167RSOUnLinkList(module);</CODE></PRE> 168 </TD> 169 </TR> 170 </TBODY> 171</TABLE> 172 173<h2>Partial Memory Deallocation of Relocatable Modules</h2> 174<p>The <code><a href="./RSOLinkList.html">RSOLinkListFixed</a></code> function links the specified module and deallocates part of the memory occupied by the dynamic module.<br>Once the module is linked using the <code><a href="./RSOLinkList.html">RSOLinkListFixed</a></code> function, the memory space that comes after (specified by <code><a href="./RSOGetFixedSize.html">RSOGetFixedSize</a></code>) can be used for any purpose (for example, for the BSS area).<br>However, several restrictions may apply, depending on the deallocation timing. (See <code><a href="./RSOLinkList.html">RSOLinkListFixed</a></code> for details.)<br>Also note that the location specified by <code><a href="./RSOGetFixedSize.html">RSOGetFixedSize</a></code> is converted from the file offset to the virtual address when the module is linked. <br> 175</p> 176<p> 177The following is an example of partial deallocation of module memory and its reuse as a BSS region. 178</p> 179<TABLE border="1" width="95%"> 180 <TBODY> 181 <TR> 182 <TD width="100%"> 183 <PRE><CODE> 184int fixed_level // deallocation stage 185RSOObjectHeader* module; // Target dynamic module 186u32 fixed_size; 187u32 new_arenaLo; 188u32 old_arenaLo; 189 190// 191fixed_size = RSOGetFixedSize(module,fixed_level); 192// 193bss = (u8 *)((u32)module + fixed_size); 194// 32 byte alignment 195bss = (u8*) OSRoundUp32B(bss); 196 197new_arenaLo = ((u32)bss + (u32)module->bssSize); 198new_arenaLo = OSRoundUp32B(new_arenaLo); 199old_arenaLo = (u32)OSGetMEM1ArenaLo(); 200// 201if (module->bssSize > 0) { 202 if(old_arenaLo < new_arenaLo) { 203 // If the region is to increase, increase before RSOLocateObjectFixed 204 OSSetMEM1ArenaLo((void*)new_arenaLo); 205 } 206} else { 207 bss = NULL; 208} 209// Link process 210RSOLinkListFixed(module,bss,i_fixed_level); 211// If the region is to decrease, decrease after RSOLocateObjectFixed 212if(bss == NULL || old_arenaLo > new_arenaLo) { 213 OSSetMEM1ArenaLo((void*)new_arenaLo); 214}</CODE></PRE> 215 </TD> 216 </TR> 217 </TBODY> 218</TABLE> 219 220<h2>Required Alignment Conditions for Relocatable Modules</h2> 221<p> 222Dynamic modules and <CODE>bss</CODE> sections both have address-alignment constraints. The dynamic module must be aligned at the maximum alignment value required by the <CODE>.init</CODE>, <CODE>.text</CODE>, <CODE>.ctor</CODE>, <CODE>.dtor</CODE>, <CODE>.rodata</CODE>, and <CODE>.data</CODE> sections. A <CODE>bss</CODE> section must be aligned at the maximum alignment value required by the data item within the <CODE>bss</CODE> section. Typically, both dynamic modules and <CODE>bss</CODE> sections require 8-byte alignment. 223</p> 224<h2>Accessing a Dynamic Module's Functions and Variables from the Static Module</h2> 225<p> 226To access dynamic module functions and variables from the static module, the address is acquired by using <code><a href="./RSOFindExportSymbolAddr.html">RSOFindExportSymbolAddr</a></code> based on the linked module information and label name.<br> 227</p> 228<p> 229The following example acquires and uses the addresses of the <code>int foo(int a);</code> function and the <code>int g_int;</code> variable from the dynamic module.<br> 230</p> 231<TABLE border="1" width="95%"> 232 <TBODY> 233 <TR> 234 <TD width="100%"> 235 <PRE><CODE> 236int (*foo)(int); 237int *g_int; 238 239foo = (int (*)(int)) RSOFindExportSymbolAddr(module,"foo"); 240g_int = (int *)RSOFindExportSymbolAddr(module,"g_int"); 241 242*g_int += foo(3); 243</CODE></PRE> 244 </TD> 245 </TR> 246 </TBODY> 247</TABLE> 248<h2>Notes</h2> 249<p> 250 251</p> 252<h2>Note: Using C++ Global Constructors in Dynamic Modules</h2> 253<p> 254If using C++ global constructors in relocatable modules, you must manually call global constructors and destructors from the module <code>_prolog</code> and <code>_epilog</code>, Code examples for each case follow below. 255</p> 256<TABLE border="1" width="95%"> 257 <TBODY> 258 <TR> 259 <TD width="100%"> 260 <PRE><CODE>#ifdef __cplusplus 261extern "C" { 262#endif 263 264typedef void (*voidfunctionptr) (void); /* ptr to function returning void */ 265__declspec(section ".init") extern voidfunctionptr _ctors[]; 266__declspec(section ".init") extern voidfunctionptr _dtors[]; 267 268void _prolog(void); 269void _epilog(void); 270void _unresolved(void); 271 272#ifdef __cplusplus 273} 274#endif 275 276void _prolog(void) 277{ 278 voidfunctionptr *constructor; 279 280 /* 281 * call static initializers 282 */ 283 for (constructor = _ctors; *constructor; constructor++) { 284 (*constructor)(); 285 } 286} 287 288void _epilog(void) 289{ 290 voidfunctionptr *destructor; 291 292 /* 293 * call destructors 294 */ 295 for (destructor = _dtors; *destructor; destructor++) { 296 (*destructor)(); 297 } 298}</CODE></PRE> 299 </TD> 300 </TR> 301 </TBODY> 302</TABLE> 303<P>In addition, make sure that each dynamic module is linked to <code>global_destructor_chain.c</code> (in the <code>$(CWFOLDER)/PowerPC_EABI_Support/Runtime/Src</code> folder). Linking to this file guarantees that each global destructor is called every time the <code>_epilog</code> function of the module is called. Otherwise, module global variables in each module are linked to the global destructor chain in the <STRONG>static</STRONG> module, and if no static module exists, destructors are never called.?<B>Note:</B> Since <CODE>Runtime.PPCEABI.H.a</CODE> uses small data sections and contains unnecessary functions, dynamic modules cannot be linked to it.</P> 304 305<h2>Note: Use caution when placing a dynamic module in external main memory (the MEM2 region)</h2> 306<p> 307Typically, branch instructions (<CODE>bx</CODE>) have only a 28-bit offset (±32 MB). Therefore, when a relocatable module is placed in external main memory (<CODE>MEM2</CODE>), it cannot access functions or variables in internal main memory (<CODE>MEM1</CODE>).<br> Avoid this issue by using <CODE>pragma</CODE> or by using <code><a href="./RSOLinkFar.html">RSOLinkFar</a></code> and <code><a href="./RSOLinkJump.html">RSOLinkJump</a></code>.<BR> 308</p> 309<H3>1. Using Pragma</H3> 310<p> 311Indicate to the compiler that the module needs to be branched in a 32-bit absolute address, using <CODE>pragma</CODE>.<BR>An example is given of branching the <CODE>foo</CODE> function (located in <CODE>MEM1</CODE>) to an absolute address. This applies whether the target function is in a static module or a dynamic (relocatable) module.<BR> Also take similar precautions when calling functions in <CODE>MEM2</CODE> from a dynamic module in <CODE>MEM1</CODE>. 312</p> 313<TABLE border="1" width="95%"> 314 <TBODY> 315 <TR> 316 <TD width="100%"> 317 <PRE><CODE> 318#pragma section code_type ".text" data_mode=far_abs code_mode=far_abs 319#pragma section RX ".init" ".init" data_mode=far_abs code_mode=far_abs 320 321void foo(void); 322 323#pragma section code_type ".text" data_mode=far_abs code_mode=pc_rel 324#pragma section RX ".init" ".init" data_mode=far_abs code_mode=pc_rel 325</CODE></PRE> 326 </TD> 327 </TR> 328 </TBODY> 329</TABLE> 330<p> 331<B>Note</B> as of 2006/06/15:<br>Certain run-time codes may not be properly called in 32-bit codes in the release version.<br>As a temporary workaround, use the <CODE>use_lmw_stmw pragma</CODE> to avoid using those runtime codes.<br> The <CODE>pragma</CODE> directive should be applied to the source of modules placed in <CODE>MEM2</CODE>.<br>The compile option "<code>-use_lmw_stmw on</code>" may also be used for the same effect.<br> 332</p> 333<TABLE border="1" width="95%"> 334 <TBODY> 335 <TR> 336 <TD width="100%"> 337 <PRE><CODE> 338// Tentatively set "<CODE>use_lmw_stmw</CODE>" to <CODE>ON</CODE>. 339#pragma use_lmw_stmw on 340</CODE></PRE> 341 </TD> 342 </TR> 343 </TBODY> 344</TABLE> 345<H3>2. Using RSOLinkFar</H3> 346<p> 347Because using just the standard <code><a href="./RSOLink.html">RSOLink</a></code> causes this issue, re-link the modules located in main memory (both <CODE>MEM1</CODE> and <CODE>MEM2</CODE>) using <code><a href="./RSOLinkFar.html">RSOLinkFar</a></code>. <code><a href="./RSOLinkFar.html">RSOLinkFar</a></code> places relay jump codes in <code><I>buff</I></code>. The linking modules then link to these jump codes to access the referenced modules in <CODE>MEM2</CODE>.<br>In the following example function <code>LinkFar</code>, the linked module (<code>i_rsoImp</code>) and the referenced module (<code>i_rsoEx</code>) are linked using a relay jump code. The return value is a pointer to the allocated buffer. The required buffer size is obtained using <code><a href="./RSOGetFarCodeSize.html">RSOGetFarCodeSize</a></code> and then allocated. It is then linked using <code><a href="./RSOLinkFar.html">RSOLinkFar</a></code>. 348</p> 349<TABLE border="1" width="95%"> 350 <TBODY> 351 <TR> 352 <TD width="100%"> 353 <PRE><CODE> 354static u32* LinkFar(RSOObjectHeader *i_rsoImp,RSOObjectHeader *i_rsoExp) 355{ 356 int a_size = RSOGetFarCodeSize(i_rsoImp,i_rsoExp); 357 u32 *a_buff; 358 359 // 360 if(a_size == 0) { 361 // not needed 362 return NULL; 363 } 364 // 365 a_buff = OSAllocFromArenaLo((u32)a_size,4); 366 // 367 RSOLinkFar(i_rsoImp,i_rsoExp,a_buff); 368 return a_buff; 369} 370</CODE></PRE> 371 </TD> 372 </TR> 373 </TBODY> 374</TABLE> 375<p> 376<B>Note:</B> Allocate the buffer from the same main memory (<CODE>MEM2</CODE> or <CODE>MEM1</CODE>) as the module being linked (<CODE>i_rsoImp</CODE>).<br>In addition, the code in the module is overwritten normally after linking. Thus, when using <code><a href="./RSOLinkList.html">RSOLinkListFixed</a></code>, proceed to <code><a href="./RSOFixedLevel.html">RSO_FL_INTERNAL</a></code> at the release stage. 377</p> 378 379<H3>3. Using RSOLinkJump</H3> 380<p> 381<code><a href="./RSOLinkJump.html">RSOLinkJump</a></code> creates a relay code to the module being referenced. The referencing side then uses it to link.<br> To create a relay code, use <code><a href="./RSOGetJumpCodeSize.html">RSOGetJumpCodeSize</a></code> to obtain the necessary buffer size, and then use <code><a href="./RSOMakeJumpCode.html">RSOMakeJumpCode</a></code> to create the relay code.<br> 382 383</p> 384<TABLE border="1" width="95%"> 385 <TBODY> 386 <TR> 387 <TD width="100%"> 388 <PRE><CODE> 389static u32 *MakeJumpCode(RSOObjectHeader *i_rsoExp) 390{ 391 int a_size = RSOGetJumpCodeSize(i_rsoExp); 392 u32 *a_buff; 393 394 // 395 if(a_size == 0) { 396 // not needed 397 return NULL; 398 } 399 // 400 a_buff = OSAllocFromArenaLo((u32)a_size,4); 401 // 402 RSOMakeJumpCode(i_rsoExp,a_buff); 403 return a_buff; 404} 405</CODE></PRE> 406 </TD> 407 </TR> 408 </TBODY> 409</TABLE> 410<p> 411Link with the created buffer and <code><a href="./RSOLinkJump.html">RSOLinkJump</a></code>. 412</p> 413<TABLE border="1" width="95%"> 414 <TBODY> 415 <TR> 416 <TD width="100%"> 417 <PRE><CODE> 418{ 419 u32 *buff = MakeJumpCode(rsoExp); 420 RSOLinkJump(rsoImp,rsoExp,buff); 421} 422</CODE></PRE> 423 </TD> 424 </TR> 425 </TBODY> 426</TABLE> 427 428<H2>Revision History</H2> 429<p> 4302006/12/19 Added a description for <code>RSOLinkJump</code>.<br>2006/10/25 Added a description for <code>RSOLinkFar</code>.<br> 2006/06/14 Initial version.<br> 431</p> 432 433<hr><p>CONFIDENTIAL</p></body> 434</html> 435