Table of Contents

Library purpose

YAHM library was designed for simple migration from ARM-based hack to standalone application. With help of YAHMlib you can easily implement syscall patching inside your application.

Library review

YAHMLib has 3 layers of API. All API's are implemented as m68k functions.

The benefits of YAHMLib

Current documentation assumes that reader already knows how to create hack. Only YAHMLib API is duscussed below.

Library integration

YAHM library can be used with both CW and GCC compilers. Just include lowlevel.c and trapcontrol5.c sources to your project. yahm_lib.h header contains all YAHM API functions. Include 5 arm resources into target executable.

Also you can include YahmLibrary.rcp into your project:

#include "yahm_int.h"


DATA "armc" ID YAHM_INIT_RES_ID "armc270E.bin"
DATA "armc" ID YAHM_SET_TRAP_RES_ID "armc270F.bin"

DATA "armc" ID YAHM_FAT_THUNK_RES_ID "fatthunk.bin"
DATA "armc" ID YAHM_SHORT_RES_ID "SHORT.BIN"
DATA "armc" ID  YAHM_SHORT_OLD_RES_ID "shorttoold.bin"
DATA "armc" ID  YAHM_CW_THUNK_RES_ID "cwthunk.bin"

Error codes

YAHM library return some custom errors:

High level API

High level API is the simplest one. Just move all resources from hack to standalone application. API contains of two functions: one for hack activation and one for hack deactivation.

Err YAHM_InstallHack(void);

Err YAHM_UninstallHack(void);

YAHM_InstallHack install all 'armc' resources from current application. Alse initialization 'armc' 999 resource is called before if exists.

YAHM_UninstallHack uninstall patches that were installed with YAHM_InstallHack.

Known issues for hack to application migration: Check type of application in hack code. Now it's 'appl', not the 'code'. Implement configuration screen manually. It's much simple than writing a hack configuration panel.

Middle level API

Use middle level instead of high level if you want flexible trap patching. High level call middle level functions for each 'armc' resource.

Err YAHM_ExecuteInitialization(void *initCodeResource, Boolean init);
// initCodeResource - pointer to initialization arm code
// init - true for initialization, false for deinitialization

Err YAHM_InstallTrap(MemHandle hTrapCode, MemHandle hGot, MemHandle hTrapInfo, UInt32 creator, UInt16 resId);
// hTrap code - handle for trap arm code chunk (or resource)
// hGot - handle for gcc GOT section, pass NULL for CodeWarrior 
// hTrapInfo - handle for TRA5 resource with YAHM_SyscallInfo5 structure
// creator, resId - those parameters are used for FtrSet(creator, resId, oldTrapAddress) 

void YAHM_UninstallTrap(MemHandle hTrap, UInt32 creator, UInt16 resID);
// hTrap code - handle for trap arm code chunk (or resource)
// creator, resId - those parameters are used for restoring old address from FtrGet(creator, resId, &oldTrapAddress) 


void *YAHM_FixupGccCode(MemHandle hGot, void *pCodeResource, void* *ppGotPtr);
void *YAHM_FixupGccCodeEx(MemHandle hGot, MemHandle  hCodeResource, void* *ppGotPtr);
// pCodeResource - pointer to arm code chunk
// hCodeResource - pointer to arm code chunk
// hGotResource - handle for gcc GOT section, pass NULL for CodeWarrior 
// ppGotPtr - pointer to GOT into relocated chunk
// return value - pointer to relocated chunk or codeResource if GOT section is absent

void YAHM_FreeRelocatedChunk(void *pRelocatedCode);

YAHM_ExecuteInitialization used for calling initialization/deinitialization resouce manually.

Call YAHM_InstallTrap to install trap. Pass handles for code, .got, trap info for proper installation. Function save old syscall pointer to feature with creator and resId parameters.

Call YAHM_UninstallTrap to uninstall trap.

.got section

Compilation with arm-gcc creates ELF executable file and extracts code section from it. Creating position-independent code (PIC) in ELF executable creates additional .got section. Code uses .got section to evaluate function addresses and literal strings offsets. build-prc from YAHM SDK includes .got section into target .prc file with the same ResID as appropriate armc resource has. YAHM loads both armc and .got and merge it into single resource in dynamic heap. High and Middle levels load .got section too. YAHM_FixupGccCode and YAHM_FixupGccCodeEx function can be used to load resource with .got section manually. Those functions merge code resource (passed in hCodeResorce or pCodeResource parameters) and .got resource (passed in hGotResource parameter). Function returns an address of relocated chunk in dynamic memory or NULL if there are no enough memory. ppGotPtr parameter points to .got section on exit. This parameter value can be used to set R10 register for PIC arm code.

YAHM_FreeRelocatedChunk can be used for freeing relocated code chunk.

hGotResource parameter can be set to NULL. In this case functions don't make relocation and return pCodeResource as relocated address value. If relocated address is found in storage memory, then YAHM_FreeRelocatedChunk doesn't free chunk. This feature can be used to load and relocate both GCC and CW resources similary.

YAHMLib v1.07+ checks for NVFS manager existence and copies all code resources into dynamic heap to avoid problems with NVFS DBCache.

Low level API

Low level API mimics pre-OS5 API. Only two functions for setting and retrieving trap handler address. Those functions require deep knowledge of ARM programming.

void *YAHM_GetTrapAddress(UInt32 base, UInt32 offset);

void *YAHM_SetTrapAddress(UInt32 base, UInt32 offset, void *trapHandler);

User-defined functions

YAHMLib requires few user-defined functions to work. Developer should implement those simple functions manually. The simplest version are showed below.

Persistent settings

typedef struct{ // Global YAHM settings. Should be saved in preferences.
        UInt32 protectYAHM; // if true, then YAHM protect application database
        UInt32 thunkCount;        // number of trap slots. allocate at least 40-50 slots.
}YAHM_persistSettings;

// copy persist settings to structure, allocated by YAHM
extern void YAHM_GetPersistSettings(YAHM_persistSettings *pSettings);

// implementation sample
void YAHM_GetPersistSettings(YAHM_persistSettings *pSettings){
        pSettings->protectYAHM = true;
        pSettings->thunkCount = 40;
}

YAHMLibrary require persistent setting to work. Developer should implement YAHM_GetPersistSettings function for changing library behaviour. Those settings can be either set in code or can be changed by user.

Runtime settings

typedef struct{ // Runtime YAHM settings. They are valid on single YAHM execution. Should be saved in feature pointer
        UInt32 activeHacksCount;
        void *pPool;
}YAHM_runtimeSettings;

extern void YAHM_SetRuntimeSettings(YAHM_runtimeSettings *pSettings);
// return ptr to runtime settings structure.
extern YAHM_runtimeSettings *YAHM_GetRuntimeSettingsPtr(void);

// callback function. 
extern void YAHM_warnAboutIncompatibleUpdate(void);


// sample implementation
void YAHM_SetRuntimeSettings(YAHM_runtimeSettings *pSettings)
{
         FtrSet(MY_CRID, YAHM_FTR_ID, (UInt32)pSettings);
}

YAHM_runtimeSettings *YAHM_GetRuntimeSettingsPtr(void)
{
        YAHM_runtimeSettings *pSet = NULL;
        FtrGet(CRID, YAHM_FTR_ID, (UInt32 *)&pSet);
        if (pSet ===== NULL){
                pSet = MemPtrNew(sizeof(YAHM_runtimeSettings));
                YAHM_SetRuntimeSettings(pSet);
                MemPtrSetOwner(pSet, 0);
                MemSet(pSet, sizeof(YAHM_runtimeSettings), 0);
        }
        return pSet;
}

Developer is responsible for allocating and saving YAHM library runtime settings. YAHM_GetRuntimeSettingsPtr function should return pointer to persistent structure. For the first time this function should allocate memory chunk for settings. The best way is saving pointer to structure in feature memory. Runtime settings should be valid from the first hack activation up to device reset. You can share one runtime settings between different programs.

Function YAHM_warnAboutIncompatibleUpdate is called when several programs (or two different program versions) are used different versions of YAHM Library. This function usually should call SysFatalAlert.

The meaning of thunk types

Thunk is a piece of code and data that sits between syscall table and your patch code. Thunk was introduced to solve two problems: to prevent patch chain breaks and to execute runtime startup.

Different thunk types require different code configurations. Currently YAHMLib supports three type of thunks.

Thunks for GCC

Thunks for CodeWarrior