From 21f35a34f0c232230d64a3e910cda4f9c73e508e Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Wed, 3 May 2006 21:45:14 +0000 Subject: [PATCH] Add patches for native GetNamedResource() and Get1NamedResource(). This will be useful to fix a bug in the AppleShare extension (see DRVR .AFPTranslator in Basilisk II) Unrelated improvement: call sheepshaver_cpu::get_resource() directly, don't get it through another global function. --- SheepShaver/src/include/rsrc_patches.h | 1 + SheepShaver/src/include/thunks.h | 3 + SheepShaver/src/include/xlowmem.h | 2 + SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp | 73 ++++------ SheepShaver/src/rsrc_patches.cpp | 135 +++++++++++++++++++ SheepShaver/src/thunks.cpp | 66 ++++++++- 6 files changed, 228 insertions(+), 52 deletions(-) diff --git a/SheepShaver/src/include/rsrc_patches.h b/SheepShaver/src/include/rsrc_patches.h index 88f96c2b..3bff5fca 100644 --- a/SheepShaver/src/include/rsrc_patches.h +++ b/SheepShaver/src/include/rsrc_patches.h @@ -22,6 +22,7 @@ #define RSRC_PATCHES_H extern void CheckLoad(uint32 type, int16 id, uint16 *p, uint32 size); +extern void CheckLoad(uint32 type, const char *name, uint16 *p, uint32 size); extern void PatchNativeResourceManager(void); #endif diff --git a/SheepShaver/src/include/thunks.h b/SheepShaver/src/include/thunks.h index 147ebc79..29d6de2e 100644 --- a/SheepShaver/src/include/thunks.h +++ b/SheepShaver/src/include/thunks.h @@ -63,6 +63,9 @@ enum { NATIVE_BITBLT, NATIVE_INVRECT, NATIVE_FILLRECT, + NATIVE_NAMED_CHECK_LOAD_INVOC, + NATIVE_GET_NAMED_RESOURCE, + NATIVE_GET_1_NAMED_RESOURCE, NATIVE_OP_MAX }; diff --git a/SheepShaver/src/include/xlowmem.h b/SheepShaver/src/include/xlowmem.h index a37282b3..07ed1048 100644 --- a/SheepShaver/src/include/xlowmem.h +++ b/SheepShaver/src/include/xlowmem.h @@ -48,6 +48,8 @@ #define XLM_EXEC_RETURN_OPCODE 0x284c // EXEC_RETURN opcode for Execute68k() #define XLM_ZERO_PAGE 0x2850 // Pointer to read-only page with all bits set to 0 #define XLM_R13 0x2854 // Pointer to .sdata section (Linux) +#define XLM_GET_NAMED_RESOURCE 0x2858 // Pointer to native GetNamedResource() routine +#define XLM_GET_1_NAMED_RESOURCE 0x285c // Pointer to native Get1NamedResource() routine #define XLM_ETHER_AO_GET_HWADDR 0x28b0 // Pointer to ethernet A0_get_ethernet_address() function #define XLM_ETHER_AO_ADD_MULTI 0x28b4 // Pointer to ethernet A0_enable_multicast() function diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp index b3ad5fcb..734f9918 100644 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp @@ -89,6 +89,7 @@ extern uintptr SignalStackBase(); // From rsrc_patches.cpp extern "C" void check_load_invoc(uint32 type, int16 id, uint32 h); +extern "C" void named_check_load_invoc(uint32 type, uint32 name, uint32 h); // PowerPC EmulOp to exit from emulation looop const uint32 POWERPC_EXEC_RETURN = POWERPC_EMUL_OP | 1; @@ -343,6 +344,13 @@ int sheepshaver_cpu::compile1(codegen_context_t & cg_context) dg.gen_invoke_T0_T1_T2((void (*)(uint32, uint32, uint32))check_load_invoc); status = COMPILE_CODE_OK; break; + case NATIVE_NAMED_CHECK_LOAD_INVOC: + dg.gen_load_T0_GPR(3); + dg.gen_load_T1_GPR(4); + dg.gen_load_T2_GPR(5); + dg.gen_invoke_T0_T1_T2((void (*)(uint32, uint32, uint32))named_check_load_invoc); + status = COMPILE_CODE_OK; + break; #endif case NATIVE_BITBLT: dg.gen_load_T0_GPR(3); @@ -971,12 +979,6 @@ void HandleInterrupt(powerpc_registers *r) } } -static void get_resource(void); -static void get_1_resource(void); -static void get_ind_resource(void); -static void get_1_ind_resource(void); -static void r_get_resource(void); - // Execute NATIVE_OP routine void sheepshaver_cpu::execute_native_op(uint32 selector) { @@ -1070,27 +1072,29 @@ void sheepshaver_cpu::execute_native_op(uint32 selector) break; } case NATIVE_GET_RESOURCE: - case NATIVE_GET_1_RESOURCE: - case NATIVE_GET_IND_RESOURCE: - case NATIVE_GET_1_IND_RESOURCE: - case NATIVE_R_GET_RESOURCE: { - typedef void (*GetResourceCallback)(void); - static const GetResourceCallback get_resource_callbacks[] = { - ::get_resource, - ::get_1_resource, - ::get_ind_resource, - ::get_1_ind_resource, - ::r_get_resource - }; - get_resource_callbacks[selector - NATIVE_GET_RESOURCE](); + get_resource(ReadMacInt32(XLM_GET_RESOURCE)); + break; + case NATIVE_GET_1_RESOURCE: + get_resource(ReadMacInt32(XLM_GET_1_RESOURCE)); + break; + case NATIVE_GET_IND_RESOURCE: + get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE)); + break; + case NATIVE_GET_1_IND_RESOURCE: + get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE)); + break; + case NATIVE_R_GET_RESOURCE: + get_resource(ReadMacInt32(XLM_R_GET_RESOURCE)); break; - } case NATIVE_MAKE_EXECUTABLE: MakeExecutable(0, gpr(4), gpr(5)); break; case NATIVE_CHECK_LOAD_INVOC: check_load_invoc(gpr(3), gpr(4), gpr(5)); break; + case NATIVE_NAMED_CHECK_LOAD_INVOC: + named_check_load_invoc(gpr(3), gpr(4), gpr(5)); + break; default: printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector); QuitEmulator(); @@ -1177,32 +1181,3 @@ uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 a const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }; return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args); } - -/* - * Resource Manager thunks - */ - -void get_resource(void) -{ - ppc_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE)); -} - -void get_1_resource(void) -{ - ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE)); -} - -void get_ind_resource(void) -{ - ppc_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE)); -} - -void get_1_ind_resource(void) -{ - ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE)); -} - -void r_get_resource(void) -{ - ppc_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE)); -} diff --git a/SheepShaver/src/rsrc_patches.cpp b/SheepShaver/src/rsrc_patches.cpp index e1a1a8e9..6f012b65 100644 --- a/SheepShaver/src/rsrc_patches.cpp +++ b/SheepShaver/src/rsrc_patches.cpp @@ -580,6 +580,22 @@ void CheckLoad(uint32 type, int16 id, uint16 *p, uint32 size) } +/* + * Resource patches via GetNamedResource() and Get1NamedResource() + */ + +void CheckLoad(uint32 type, const char *name, uint8 *p, uint32 size) +{ + uint16 *p16; + uint32 base; + D(bug("vCheckLoad %c%c%c%c (%08x) name \"%*s\", data %p, size %d\n", type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff, type, name[0], &name[1], p, size)); + + // Don't modify resources in ROM + if ((uintptr)p >= (uintptr)ROMBaseHost && (uintptr)p <= (uintptr)(ROMBaseHost + ROM_SIZE)) + return; +} + + /* * Native Resource Manager patches */ @@ -601,6 +617,23 @@ void check_load_invoc(uint32 type, int16 id, uint32 h) CheckLoad(type, id, (uint16 *)Mac2HostAddr(p), size); } +#ifdef __BEOS__ +static +#else +extern "C" +#endif +void named_check_load_invoc(uint32 type, uint32 name, uint32 h) +{ + if (h == 0) + return; + uint32 p = ReadMacInt32(h); + if (p == 0) + return; + uint32 size = ReadMacInt32(p - 2 * 4) & 0xffffff; + + CheckLoad(type, (char *)Mac2HostAddr(name), Mac2HostAddr(p), size); +} + #ifdef __BEOS__ static asm void **get_resource(register uint32 type, register int16 id) { @@ -766,6 +799,72 @@ static asm void **r_get_resource(register uint32 type, register int16 id) addi r1,r1,56+12 blr } + +static asm void **get_named_resource(register uint32 type, register uint32 name) +{ + // Create stack frame + mflr r0 + stw r0,8(r1) + stwu r1,-(56+12)(r1) + + // Save type/ID + stw r3,56(r1) + stw r4,56+4(r1) + + // Call old routine + lwz r0,XLM_GET_NAMED_RESOURCE + lwz r2,XLM_RES_LIB_TOC + mtctr r0 + bctrl + lwz r2,XLM_TOC // Get TOC + stw r3,56+8(r1) // Save handle + + // Call CheckLoad + lwz r3,56(r1) + lwz r4,56+4(r1) + lwz r5,56+8(r1) + bl named_check_load_invoc + lwz r3,56+8(r1) // Restore handle + + // Return to caller + lwz r0,56+12+8(r1) + mtlr r0 + addi r1,r1,56+12 + blr +} + +static asm void **get_1_named_resource(register uint32 type, register uint32 name) +{ + // Create stack frame + mflr r0 + stw r0,8(r1) + stwu r1,-(56+12)(r1) + + // Save type/ID + stw r3,56(r1) + stw r4,56+4(r1) + + // Call old routine + lwz r0,XLM_GET_1_NAMED_RESOURCE + lwz r2,XLM_RES_LIB_TOC + mtctr r0 + bctrl + lwz r2,XLM_TOC // Get TOC + stw r3,56+8(r1) // Save handle + + // Call CheckLoad + lwz r3,56(r1) + lwz r4,56+4(r1) + lwz r5,56+8(r1) + bl named_check_load_invoc + lwz r3,56+8(r1) // Restore handle + + // Return to caller + lwz r0,56+12+8(r1) + mtlr r0 + addi r1,r1,56+12 + blr +} #else // Routines in asm_linux.S extern "C" void get_resource(void); @@ -773,6 +872,8 @@ extern "C" void get_1_resource(void); extern "C" void get_ind_resource(void); extern "C" void get_1_ind_resource(void); extern "C" void r_get_resource(void); +extern "C" void get_named_resource(void); +extern "C" void get_1_named_resource(void); #endif void PatchNativeResourceManager(void) @@ -865,5 +966,39 @@ void PatchNativeResourceManager(void) #else WriteMacInt32(tvec, (uint32)r_get_resource); #endif +#endif + + // Patch native GetNamedResource() + upp = ReadMacInt32(0x1484); + tvec = ReadMacInt32(upp + 5 * 4); + D(bug(" GetNamedResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); + WriteMacInt32(XLM_GET_NAMED_RESOURCE, ReadMacInt32(tvec)); +#if EMULATED_PPC + WriteMacInt32(tvec, NativeFunction(NATIVE_GET_NAMED_RESOURCE)); +#else +#ifdef __BEOS__ + tvec2 = (uint32 *)get_named_resource; + WriteMacInt32(tvec, tvec2[0]); + WriteMacInt32(tvec + 4, tvec2[1]); +#else + WriteMacInt32(tvec, (uint32)get_named_resource); +#endif +#endif + + // Patch native Get1NamedResource() + upp = ReadMacInt32(0x0e80); + tvec = ReadMacInt32(upp + 5 * 4); + D(bug(" Get1NamedResource() entry %08x, TOC %08x\n", ReadMacInt32(tvec), ReadMacInt32(tvec + 4))); + WriteMacInt32(XLM_GET_1_NAMED_RESOURCE, ReadMacInt32(tvec)); +#if EMULATED_PPC + WriteMacInt32(tvec, NativeFunction(NATIVE_GET_1_NAMED_RESOURCE)); +#else +#ifdef __BEOS__ + tvec2 = (uint32 *)get_1_named_resource; + WriteMacInt32(tvec, tvec2[0]); + WriteMacInt32(tvec + 4, tvec2[1]); +#else + WriteMacInt32(tvec, (uint32)get_1_named_resource); +#endif #endif } diff --git a/SheepShaver/src/thunks.cpp b/SheepShaver/src/thunks.cpp index b8d1bf59..704de569 100644 --- a/SheepShaver/src/thunks.cpp +++ b/SheepShaver/src/thunks.cpp @@ -56,6 +56,7 @@ uint32 NativeOpcode(int selector) uint32 opcode; switch (selector) { case NATIVE_CHECK_LOAD_INVOC: + case NATIVE_NAMED_CHECK_LOAD_INVOC: opcode = POWERPC_NATIVE_OP(0, selector); break; case NATIVE_PATCH_NAME_REGISTRY: @@ -85,6 +86,8 @@ uint32 NativeOpcode(int selector) case NATIVE_GET_IND_RESOURCE: case NATIVE_GET_1_IND_RESOURCE: case NATIVE_R_GET_RESOURCE: + case NATIVE_GET_NAMED_RESOURCE: + case NATIVE_GET_1_NAMED_RESOURCE: case NATIVE_MAKE_EXECUTABLE: case NATIVE_SYNC_HOOK: case NATIVE_BITBLT_HOOK: @@ -112,9 +115,15 @@ static uint32 get_1_resource_func; static uint32 get_ind_resource_func; static uint32 get_1_ind_resource_func; static uint32 r_get_resource_func; +static uint32 get_named_resource_func; +static uint32 get_1_named_resource_func; static void generate_powerpc_thunks(void) { + // check_load_invoc() thunk + uint32 check_load_invoc_opcode = NativeOpcode(NATIVE_CHECK_LOAD_INVOC); + uint32 base; + static uint32 get_resource_template[] = { PL(0x7c0802a6), // mflr r0 PL(0x90010008), // stw r0,8(r1) @@ -152,9 +161,6 @@ static void generate_powerpc_thunks(void) } assert(xlm_index != -1 && check_load_invoc_index != -1); - uint32 check_load_invoc_opcode = NativeOpcode(NATIVE_CHECK_LOAD_INVOC); - uint32 base; - // GetResource() get_resource_func = base = SheepMem::Reserve(get_resource_template_size); Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); @@ -184,6 +190,58 @@ static void generate_powerpc_thunks(void) Host2Mac_memcpy(base, get_resource_template, get_resource_template_size); WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_R_GET_RESOURCE); WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); + + // named_check_load_invoc() thunk + check_load_invoc_opcode = NativeOpcode(NATIVE_NAMED_CHECK_LOAD_INVOC); + + static uint32 get_named_resource_template[] = { + PL(0x7c0802a6), // mflr r0 + PL(0x90010008), // stw r0,8(r1) + PL(0x9421ffbc), // stwu r1,-68(r1) + PL(0x90610038), // stw r3,56(r1) + PL(0x9081003c), // stw r4,60(r1) + PL(0x00000000), // lwz r0,XLM_GET_NAMED_RESOURCE(r0) + PL(0x80402834), // lwz r2,XLM_RES_LIB_TOC(r0) + PL(0x7c0903a6), // mtctr r0 + PL(0x4e800421), // bctrl + PL(0x90610040), // stw r3,64(r1) + PL(0x80610038), // lwz r3,56(r1) + PL(0x8081003c), // lwz r4,60(r1) + PL(0x80a10040), // lwz r5,64(r1) + PL(0x00000001), // + PL(0x80610040), // lwz r3,64(r1) + PL(0x8001004c), // lwz r0,76(r1) + PL(0x7c0803a6), // mtlr r0 + PL(0x38210044), // addi r1,r1,68 + PL(0x4e800020) // blr + }; + const uint32 get_named_resource_template_size = sizeof(get_named_resource_template); + + xlm_index = -1, check_load_invoc_index = -1; + for (int i = 0; i < get_resource_template_size/4; i++) { + uint32 opcode = ntohl(get_resource_template[i]); + switch (opcode) { + case 0x00000000: + xlm_index = i; + break; + case 0x00000001: + check_load_invoc_index = i; + break; + } + } + assert(xlm_index != -1 && check_load_invoc_index != -1); + + // GetNamedResource() + get_named_resource_func = base = SheepMem::Reserve(get_named_resource_template_size); + Host2Mac_memcpy(base, get_named_resource_template, get_named_resource_template_size); + WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_NAMED_RESOURCE); + WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); + + // Get1NamedResource() + get_1_named_resource_func = base = SheepMem::Reserve(get_named_resource_template_size); + Host2Mac_memcpy(base, get_named_resource_template, get_named_resource_template_size); + WriteMacInt32(base + xlm_index * 4, 0x80000000 | XLM_GET_1_NAMED_RESOURCE); + WriteMacInt32(base + check_load_invoc_index * 4, check_load_invoc_opcode); } #endif @@ -217,6 +275,8 @@ bool ThunksInit(void) native_op[NATIVE_GET_IND_RESOURCE].func = get_ind_resource_func; native_op[NATIVE_GET_1_IND_RESOURCE].func = get_1_ind_resource_func; native_op[NATIVE_R_GET_RESOURCE].func = r_get_resource_func; + native_op[NATIVE_GET_NAMED_RESOURCE].func = get_named_resource_func; + native_op[NATIVE_GET_1_NAMED_RESOURCE].func = get_1_named_resource_func; #endif #else #if defined(__linux__) || defined(__NetBSD__) || (defined(__APPLE__) && defined(__MACH__))