Add missing filesmaster
authorkmeaw <[email protected]>
Fri, 8 Apr 2011 01:58:03 +0000 (8 05:58 +0400)
committerkmeaw <[email protected]>
Fri, 8 Apr 2011 01:58:03 +0000 (8 05:58 +0400)
include/debug.h [new file with mode: 0644]
include/syscall_patch.h [new file with mode: 0644]
source/syscall_patch.c [new file with mode: 0644]

diff --git a/include/debug.h b/include/debug.h
new file mode 100644 (file)
index 0000000..646204b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#define PRINTF(...)
+
+#endif
diff --git a/include/syscall_patch.h b/include/syscall_patch.h
new file mode 100644 (file)
index 0000000..dcecff2
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef SYSCALL_PLUG_H
+#define SYSCALL_PLUG_H
+
+/* ---------------------------------------------------------------------------
+ * Defines
+ * -------------------------------------------------------------------------*/
+
+/** Maximum 64bit writes allowed by this framework */
+#define MAXPATCH 4
+
+/** Peek syscall */
+#define SC_PEEK 6
+
+/** Poke syscall */
+#define SC_POKE 7
+
+/** Syscall lv2FsMkdir
+ *  Used for injecting code in lv2:
+ *    - new poke with cache invalidation (peek_poke.c)
+ *    - memcpy (main.c)
+ *    - panic (main.c) */
+#define SC_SLOT_1 811
+
+/** Syscall lv2FsRmdir
+ *  Used for injecting code in HV
+ *    - hv redirections (hvcall.c) */
+#define SC_SLOT_2 813
+
+/** Syscall ?
+ *  Syscall table entry used for overwriting a jumping address */
+#define SC_SLOT_3 11
+
+/* ---------------------------------------------------------------------------
+ * Structures
+ * -------------------------------------------------------------------------*/
+
+/** Syscall context for (un)patching custom code */
+struct syscall_patch_ctx
+{
+    int syscall;               /**< Syscall number */
+    int nbpatch;               /**< Number of uint64_t writes/read to operate */
+    uint64_t backup[MAXPATCH]; /**< Backup of the original code */
+    uint64_t patch[MAXPATCH];  /**< New code to inject */
+};
+
+/* ---------------------------------------------------------------------------
+ * Functions
+ * -------------------------------------------------------------------------*/
+
+extern int
+syscall_patch(
+    struct syscall_patch_ctx* ctx,
+    int syscall,
+    int nbpatch,
+    const uint64_t* patch);
+
+extern int
+syscall_unpatch(
+    struct syscall_patch_ctx* ctx);
+
+extern void
+syscall_jumpto(
+    int syscall,
+    void* addr);
+
+#endif
diff --git a/source/syscall_patch.c b/source/syscall_patch.c
new file mode 100644 (file)
index 0000000..b78fdd9
--- /dev/null
@@ -0,0 +1,132 @@
+#include <stdint.h>
+#include <psl1ght/lv2.h>
+
+#include "syscall_patch.h"
+#include "peek_poke.h"
+
+/* ---------------------------------------------------------------------------
+ * Defines
+ * -------------------------------------------------------------------------*/
+
+#ifndef FIRMWARE
+#define FIRMWARE 355
+#endif
+
+#if FIRMWARE == 355
+#define SYSCALL_TABLE_ADDRESS 0x8000000000346570ULL
+#elif FIRMWARE == 341 || FIRMWARE == 340
+#define SYSCALL_TABLE_ADDRESS 0x80000000002EB128ULL;
+#elif FIRMWARE == 330
+#define SYSCALL_TABLE_ADDRESS 0x80000000002EA728ULL;
+#elif FIRMWARE == 321
+#define SYSCALL_TABLE_ADDRESS 0x80000000002EA8A0ULL;
+#elif FIRMWARE == 315
+#define SYSCALL_TABLE_ADDRESS 0x80000000002EA820ULL
+#else
+#error Firmware not supported
+#endif
+
+/* ---------------------------------------------------------------------------
+ * Structures
+ * -------------------------------------------------------------------------*/
+
+/** HV syscall table entry
+ * Just informative so you know why a syscall plug always requires two
+ * indirections */
+struct syscall_table_entry {
+       void *func;
+               /**< Function pointer */
+       void *toc;
+               /**< TOC pointer */
+};
+
+/* ---------------------------------------------------------------------------
+ * Module vars
+ * -------------------------------------------------------------------------*/
+
+/** Syscall table - Do not use directly, access requires privileges only
+ * lv2_peek can circumvent. This variable serves as a simple mean to get
+ * the address of an entry */
+static struct syscall_table_entry **syscall_table =
+    (struct syscall_table_entry **)SYSCALL_TABLE_ADDRESS;
+
+/* ---------------------------------------------------------------------------
+ * Functions
+ * -------------------------------------------------------------------------*/
+
+int
+syscall_patch(struct syscall_patch_ctx *ctx,
+             int syscall, int nbpatch, const uint64_t * patch)
+{
+       int i;
+       uint64_t entry;
+       uint64_t func;
+
+       if (syscall < 0 || nbpatch > MAXPATCH) {
+               return -1;
+       }
+
+       ctx->syscall = syscall;
+       ctx->nbpatch = nbpatch;
+
+       // First find the adress of the code
+       entry = lv2_peek((uint64_t) & syscall_table[syscall]);
+       func = lv2_peek(entry);
+
+       // Copy over the new code
+       for (i = 0; i < ctx->nbpatch; i++) {
+               ctx->backup[i] = lv2_peek(func);
+               ctx->patch[i] = patch[i];
+               lv2_poke(func, patch[i]);
+               func += sizeof(uint64_t);
+       }
+
+       return 0;
+}
+
+int syscall_unpatch(struct syscall_patch_ctx *ctx)
+{
+       int i;
+       uint64_t entry;
+       uint64_t func;
+
+       if (ctx->syscall < 0) {
+               return -1;
+       }
+       // First get the adress of the code
+       entry = lv2_peek((uint64_t) & syscall_table[ctx->syscall]);
+       func = lv2_peek(entry);
+
+       for (i = 0; i < ctx->nbpatch; i++) {
+               uint64_t patched = lv2_peek(func);
+               if (patched != ctx->patch[i]) {
+                       while (i--) {
+                               func -= sizeof(uint64_t);
+                               lv2_poke(func, ctx->patch[i]);
+                       }
+                       return -1;
+               }
+               lv2_poke(func, ctx->backup[i]);
+               func += sizeof(uint64_t);
+       }
+
+       ctx->syscall = -1;
+       ctx->nbpatch = 0;
+
+       return 0;
+}
+
+void syscall_jumpto(int syscall, void *addr)
+{
+       uint64_t entry = lv2_peek((uint64_t) & syscall_table[syscall]);
+       uint64_t func = lv2_peek(entry);
+
+       // Make the entry function point to the specified address
+       lv2_poke(entry, (uint64_t) addr);
+
+       // Call it
+       Lv2Syscall0(syscall);
+
+       // Retore old func entry
+       lv2_poke(entry, func);
+}