diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp index 1f8c36c0..9d253201 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp @@ -13,6 +13,13 @@ #include #include #include +#include +#include + +#if __mips__ +#include +#include +#endif #include #include @@ -235,6 +242,61 @@ struct FunctionPointers { L1_LoadKeys_V9_or_V10_t LoadKeys_V9_or_V10; }; +// The Cache Flush function is very processor dependent, but is needed by the +// haystack code. The haystack code is delivered as a static prebuilt library. +// For that reason, we pass a function pointer for cache_flush into the +// haystack. The function is combiled outside of the haystack and may use +// target (processor) specific compiler flags. +void clear_cache_function(void *page, size_t len) { + + // Note on cross platform support. If __has_builtin is not defined as a + // preprocessor function, we cannot use + // "#if defined(__has_builtin) && __has_builtin(..)". + // So, instead, we will define USED_BUILTIN_CLEAR_CACHE if both conditions + // are true, and use "#ifndef USED_BUILTIN_CLEAR_CACHE" instead of #else. +#ifdef __has_builtin +#if __has_builtin(__builtin___clear_cache) +#pragma message "clear_cache_function is using __builtin___clear_cache." +#define USED_BUILTIN_CLEAR_CACHE + char *begin = static_cast(page); + char *end = begin + len; + __builtin___clear_cache(begin, end); +#endif +#endif +#ifndef USED_BUILTIN_CLEAR_CACHE +#if __arm__ +#pragma message "clear_cache_function is using arm asm." + // ARM Cache Flush System Call: + char *begin = static_cast(page); + char *end = begin + len; + const int syscall = 0xf0002; + __asm __volatile ( + "push {r0, r1, r2, r7}\n" + "mov r0, %0\n" + "mov r1, %1\n" + "mov r7, %2\n" + "mov r2, #0x0\n" + "svc 0x00000000\n" + "pop {r0, r1, r2, r7}\n" + : + : "r" (begin), "r" (end), "r" (syscall) + : "r0", "r1", "r7" + ); +#elif __mips__ +#pragma message "clear_cache_function is using mips asm." + int result = syscall(__NR_cacheflush, page, len, ICACHE); + if (result) { + fprintf(stderr, "cacheflush failed!: errno=%d %s\n", errno, + strerror(errno)); + exit(-1); // TODO(fredgc): figure out more graceful error handling. + } +#else +#pragma message "clear_cache_function is not doing anything." + // TODO(fredgc): silence warning about unused variables. +#endif +#endif +} + struct LevelSession { FunctionPointers* fcn; OEMCrypto_SESSION session; @@ -269,7 +331,7 @@ class Adapter { OEMCryptoResult Initialize() { LoadLevel3(); - OEMCryptoResult result = Level3_Initialize(); + OEMCryptoResult result = Level3_Initialize(clear_cache_function); if (force_level3()) { LOGW("Test code. User requested falling back to L3"); return result; @@ -416,7 +478,6 @@ class Adapter { } void LoadLevel3() { - level3_.Initialize = Level3_Initialize; level3_.Terminate = Level3_Terminate; level3_.OpenSession = Level3_OpenSession; level3_.CloseSession = Level3_CloseSession; diff --git a/libwvdrmengine/level3/arm/libwvlevel3.a b/libwvdrmengine/level3/arm/libwvlevel3.a index 3b01fc9e..5cd58c0e 100644 Binary files a/libwvdrmengine/level3/arm/libwvlevel3.a and b/libwvdrmengine/level3/arm/libwvlevel3.a differ diff --git a/libwvdrmengine/level3/mips/libwvlevel3.a b/libwvdrmengine/level3/mips/libwvlevel3.a index eacfe50d..c7e977d5 100644 Binary files a/libwvdrmengine/level3/mips/libwvlevel3.a and b/libwvdrmengine/level3/mips/libwvlevel3.a differ diff --git a/libwvdrmengine/level3/x86/libwvlevel3.a b/libwvdrmengine/level3/x86/libwvlevel3.a index 9a9e7722..d16ca564 100644 Binary files a/libwvdrmengine/level3/x86/libwvlevel3.a and b/libwvdrmengine/level3/x86/libwvlevel3.a differ diff --git a/libwvdrmengine/oemcrypto/include/level3.h b/libwvdrmengine/oemcrypto/include/level3.h index f84a9baf..79e96907 100644 --- a/libwvdrmengine/oemcrypto/include/level3.h +++ b/libwvdrmengine/oemcrypto/include/level3.h @@ -64,7 +64,7 @@ namespace wvoec3 { extern "C" { bool Level3_PreInitialize(const char* path); -OEMCryptoResult Level3_Initialize(void); +OEMCryptoResult Level3_Initialize(void (*ClearCache)(void *, size_t)); OEMCryptoResult Level3_Terminate(void); OEMCryptoResult Level3_OpenSession(OEMCrypto_SESSION *session); OEMCryptoResult Level3_CloseSession(OEMCrypto_SESSION session); @@ -80,7 +80,6 @@ OEMCryptoResult Level3_GenerateSignature(OEMCrypto_SESSION session, size_t message_length, uint8_t* signature, size_t* signature_length); - OEMCryptoResult Level3_LoadKeys(OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,