about summary refs log tree commit diff stats
path: root/src/tools/wine_tools.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-02-28 14:19:04 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-02-28 14:19:04 +0100
commite753c19da1b621b1e667de85ce5ef60d186f0684 (patch)
tree9bc80378efbe42ec72678230de2905ab121a4d8f /src/tools/wine_tools.c
parent7b50468b61b7bdd9a15753c0a28711c1654a8c12 (diff)
downloadbox64-e753c19da1b621b1e667de85ce5ef60d186f0684.tar.gz
box64-e753c19da1b621b1e667de85ce5ef60d186f0684.zip
Added some minimal set of source (now box64 compile and say hello at least)
Diffstat (limited to 'src/tools/wine_tools.c')
-rwxr-xr-xsrc/tools/wine_tools.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/tools/wine_tools.c b/src/tools/wine_tools.c
new file mode 100755
index 00000000..6fa7a47d
--- /dev/null
+++ b/src/tools/wine_tools.c
@@ -0,0 +1,107 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "wine_tools.h"
+#include "debug.h"
+#include "box64context.h"
+
+typedef struct wine_prereserve_s
+{
+    void*   addr;
+    size_t  size;
+} wine_prereserve_t;
+
+// only the prereseve argument is reserved, not the other zone that wine-preloader reserve
+static wine_prereserve_t my_wine_reserve[] = {{(void*)0x00010000, 0x00008000}, {(void*)0x00110000, 0x30000000}, {(void*)0x7f000000, 0x03000000}, {0, 0}, {0, 0}};
+
+int wine_preloaded = 0;
+
+static int get_prereserve(const char* reserve, void** addr, size_t* size)
+{
+    if(!reserve)
+        return 0;
+    uintptr_t r = 0;
+    int first = 1;
+    while(*reserve) {
+        // numbers reading
+        if(*reserve>='0' && *reserve<='9')  r=r*16+(*reserve)-'0';
+        else if(*reserve>='A' && *reserve<='F')  r=r*16+(*reserve)-'A'+10;
+        else if(*reserve>='a' && *reserve<='f')  r=r*16+(*reserve)-'a'+10;
+        else if(*reserve=='-') {if(first) {*addr=(void*)(r&~(box64_pagesize-1)); r=0; first=0;} else {printf_log(LOG_NONE, "Warning, Wine prereserve badly formated\n"); return 0;}}
+        else {printf_log(LOG_NONE, "Warning, Wine prereserve badly formated\n"); return 0;}
+        ++reserve;
+    }
+    *size = r;
+    return 1;
+}
+
+static void add_no_overlap(void* addr, size_t size)
+{
+    int idx = 0;
+    while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) {
+        if(addr>=my_wine_reserve[idx].addr && addr<my_wine_reserve[idx].addr+my_wine_reserve[idx].size) {
+            // overlap
+            if (addr+size > my_wine_reserve[idx].addr+my_wine_reserve[idx].size)
+                // need adjust size
+                my_wine_reserve[idx].size = (intptr_t)addr-(intptr_t)my_wine_reserve[idx].addr+size;
+            return;
+        }
+        ++idx;
+    }
+    my_wine_reserve[idx].addr = addr;
+    my_wine_reserve[idx].size = size;
+}
+
+void wine_prereserve(const char* reserve)
+{
+    void* addr = NULL;
+    size_t size = 0;
+
+    if(get_prereserve(reserve, &addr, &size)) {
+        add_no_overlap(addr, size);
+    }
+
+    int idx = 0;
+    while(my_wine_reserve[idx].addr && my_wine_reserve[idx].size) {
+        void* p = mmap(my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 
+                    PROT_NONE, /*MAP_FIXED |*/ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0);
+        if(p==(void*)-1 || p!=my_wine_reserve[idx].addr) {
+            printf_log(LOG_NONE, "Warning, prereserve of %p:0x%x failed (%s)\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size, strerror(errno));
+            if(p!=(void*)-1)
+                munmap(p, my_wine_reserve[idx].size);
+            my_wine_reserve[idx].addr = NULL;
+            my_wine_reserve[idx].size = 0;
+        } else {
+            printf_log(LOG_DEBUG, "WINE prereserve of %p:0x%x done\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
+            ++idx;
+        }
+    }
+
+    wine_preloaded = 1;
+}
+
+void* get_wine_prereserve()
+{
+    if(!wine_preloaded)
+        wine_prereserve(NULL);
+    return (void*)my_wine_reserve;
+}
+
+#ifdef DYNAREC
+void dynarec_wine_prereserve()
+{
+    #if 0
+    // disable for now, as it break some installer
+    if(!wine_preloaded)
+        wine_prereserve(NULL);
+    // don't reserve the initial arbritrary block as "with linker", it's not true
+    for(int i=1; i<sizeof(my_wine_reserve)/sizeof(my_wine_reserve[0]); ++i)
+        if(my_wine_reserve[i].addr && my_wine_reserve[i].size)
+            addDBFromAddressRange(my_context, (uintptr_t)my_wine_reserve[i].addr, my_wine_reserve[i].size, 0);  // prepare the prereserved area for exec, with linker
+    #endif
+}
+#endif